the other dell

Introduction - Exercise 1.2 A Random Walker with vectors

Take one of the walker examples from the introduction and convert it to use PVectors.

PVectors are a built-in class representing vectors. They encapsulate 2 and 3-dimensions and provide methods for vector arithmatic and geometry.

To get anything useful out, I had to refactor most of the code that worked with co-ordinates rather than do it one step at a time.

void vEllipse( PVector origin, float x_rad, float y_rad ) {
  ellipse( origin.x, origin.y, x_rad, y_rad );
}


class Walker {
  PVector origin;
  PVector step = new PVector(0, 0);
  float tx,ty;
  float radius = 16;

  Walker() {
    origin = new PVector( width / 2, height / 2 );
    tx = 3;
    ty = 10000;
  }

  void display() {
    vEllipse(origin, radius, radius);
  }

  void step() {
    PVector clone = origin.copy();
    step.x = map(noise(tx), 0, 1, -10, 10);
    step.y = map(noise(ty), 0, 1, -10, 10);

    clone.add( step );
    if( clone.x < 0 || clone.x > width ) step.x = -step.x;
    if( clone.y < 0 || clone.y > height ) step.y = -step.y;

    origin.add( step );

    tx += 0.04;
    ty += 0.04;
  }
}

Walker w;

void setup() {
  background(255);
  size( 640, 360 );
  w = new Walker();
}

void draw() {
  w.step();
  w.display();
}

The instance variables x and y get combined into PVector origin, and likewise step_x and step_y are joined as PVector step. Both of these are declared in the class definition. I provided a default value for step and radius in the class definition, but initialised origin in the constructor, mostly just to see what would happen.

The changes to draw() are more fun. I’ve become frustrated with the Walkers walking off the edge of the screen, so I did some basic collision detection. First I clone origin and PVector.add() the Perlin-derrived step vector. Next I check whether the updated position is outside the box. If it is, I reverse the modifier for the dimension that has collided with the wall. The check is basic: it works against the origin rather than the edge of the circle (although updating to fix this would be easy). Having updated the steps, I PVector.add() them to origin proper and update the time variables. I felt the time variables didn’t need to be vectors, although I suppose they could be (and incrementing them would also be done with PVector.add()).

At first, I forgot to initialise step. When I tried to add the Perlin noise to the unitiailised vector properites (step.x and step.y) I was handed a Null Pointer Exception. There will be no .x or .y of an uninitialised object!

I lifted the vEllipse() function created in the previous example, just because.

The Coiling Tentacle of Perlin