首页 > 解决方案 > Natural Movement with Noise

问题描述

Im creating an object that randomly moves in a natural way using noise like this (works as intended):

The objects encounter a collision and their trajectory is manipulated, the movement path now changes to straight line (words as intended)

thisRabbit.x = _world.width * (noise(thisRabbit.t));
thisRabbit.y = _world.height * (noise(thisRabbit.t+5));
thisRabbit.t += 0.001;

The problem is after this movement , i want the object to start moving in a random direction again as it was initially. If i use the same function, the object jumps to the last location before the trajectory was modified.

let vx = this.acquiredFood[0] - this.x;
let vy = this.acquiredFood[1] -  this.y;

let f = (this.genes.speed + 10) / Math.sqrt(vx*vx+vy*vy);

vx = vx * f;
vy = vy * f;

let newX = this.x + vx;
let newY = this.y + vy;

So how do i get the object to move as before, given a starting position

edit: snippet here: https://editor.p5js.org/vince.chinner/sketches/HPFKR8eIw

标签: javascriptp5.jsnoise

解决方案


Your problem is that you used a factor from 0 to 1 generated with noise and an incremented seed to generate the position by multiplying directly the world dimentions. When reaching food, you cannot increment the seed as to be in the exact position where the movement to get your food led you (I found no inverse function for noise to get the seed from the return value).

What you need to do instead is use the noise to increment or decrement the coordinates, so that no matter where the seed is, you don't loose your current position.

Here are the different corrections I applied to the code, as there were also syntax errors, I can't really paste the whole stuff here for copyright reasons (you didn't share the whole code here and the sketch belongs to you)

MAIN CORRECTION:

  • used a var found because returning from the forEach callback doesn't make you leave the findFood function, but the callback one. And the forEach loop doesn't stop. Using this var prevents the further forEach tests to be made and allows you to return from findFood so that no further move is made after seeing food.
  • noise is now applied to a value of 4 and I subtract 2, so that x and y now change with a range of -2 to 2 each. Of course, with this method, you need to check against world dimentions or else the rabbit could leave the world. The seed increment has been changed too or else it would vary too slowly (adapt values as you wish)
  findFood(){
    var thisRabbit = this, found = false;
    _world.food.forEach(f => {
      if(!found){
        let d = int(dist(f[0], f[1], thisRabbit.x, thisRabbit.y));
        if(d < (thisRabbit.genes.vision / 2)+3){
          thisRabbit.state = "foundFood";
          this.acquiredFood = f;
          found = true;
        }
      }
    });
    if(found){ return; }
    thisRabbit.x += (noise(thisRabbit.t) * 4) - 2;
    if(thisRabbit.x < 0){ thisRabbit.x = 0; }
    if(thisRabbit.x > _world.width){ thisRabbit.x = _world.width; }
    thisRabbit.y += (noise(thisRabbit.t + 5) * 4) - 2;
    if(thisRabbit.y < 0){ thisRabbit.y = 0; }
    if(thisRabbit.y > _world.height){ thisRabbit.y = _world.height; }
    thisRabbit.t += 0.01;
  }

SYNTAX ERRORS:

lines 23 / 24: assignment should be with a value (null or false)

    this.genes = null;
    this.acquiredFood = null;

lines 129 to 133: end you instructions with a ; instead of a ,

    this.width = w;
    this.height = h;
    this.foodDensity = foodDensity;
    this.food = [];
    this.rabits = [];

line 156 to 160: there should be no space between rabbit and .t. Additionnally, because the coordinates are not directly linked to t, I would prefer to use random for starting position:

      let x = this.width * random();
      let y = this.height * random();
      let _rabbit = new rabbit(x, y);
      _rabbit.genes = genes;
      _rabbit.t = t;

推荐阅读