// The Nature of Code // Daniel Shiffman // http://natureofcode.com // Flow Field Following class Vehicle { //The usual stuff PVector position; PVector velocity; PVector acceleration; float r; float maxforce; // Maximum steering force float maxspeed; // Maximum speed Vehicle(PVector l, float ms, float mf) { position = l.get(); r = 5.0; maxspeed = ms; maxforce = mf; acceleration = new PVector(0,0); velocity = new PVector(0,0); } public void run() { update(); borders(); display(); } //Implementing Reynolds' flow field following algorithm //http://www.red3d.com/cwr/steer/FlowFollow.html void follow(FlowField flow) { // What is the vector at that spot in the flow field? PVector desired = flow.lookup(position); // Scaleit up by maxspeed desired.mult(maxspeed); // Steering is desired minus velocity PVector steer = PVector.sub(desired, velocity); PVector randomSteer = new PVector(random( -0.9,0.9), random( -0.9,0.9)); steer = PVector.sub(steer, randomSteer); // Limit to maximum steering force steer.limit(0.01); applyForce(steer); } void applyForce(PVector force) { // We could add mass here if we want A = F / M acceleration.add(force); } //Method to update position void update() { // Update velocity velocity.add(acceleration); // Limit speed velocity.limit(maxspeed); position.add(velocity); // Reset accelertion to 0 each cycle acceleration.mult(0); } void display() { stroke(color(40, 49, 73)); circle(position.x, position.y ,2); } //Wraparound void borders() { if (position.x < - r) { //left border position.x = width + r; position.y = position.y + random( -100,100); } if (position.y < - r) { //top position.y = height + r; position.x = position.x + random( -100,100); } if (position.x > width + r) { // right border position.x = -(r); position.y = position.y + random( -100,100); } if (position.y > height + r) { //bottom position.y = -(r); position.x = position.x + random( -100,100); } } }