// Flow Field Following // Daniel Shiffman // The Nature of Code, Spring 2009 class Boid { // The usual stuff PVector loc; PVector vel; PVector acc; float r; float maxforce; // Maximum steering force float maxspeed; // Maximum speed Boid(PVector l, float ms, float mf) { loc = l.get(); r = 3.0f; maxspeed = ms; maxforce = mf; acc = new PVector(0,0); vel = new PVector(0,0); } public void run() { update(); borders(); render(); } // Implementing Reynolds' flow field following algorithm // http://www.red3d.com/cwr/steer/FlowFollow.html void follow(FlowField f) { // Look ahead PVector ahead = vel.get(); ahead.normalize(); ahead.mult(32); // Arbitrarily look 32 pixels ahead PVector lookup = PVector.add(loc,ahead); // Draw in debug mode if (debug) { stroke(0); line(loc.x,loc.y,lookup.x,lookup.y); fill(0); ellipse(lookup.x,lookup.y,3,3); } // What is the vector at that spot in the flow field? PVector desired = f.lookup(lookup); // Scale it up by maxspeed desired.mult(maxspeed); // Steering is desired minus velocity PVector steer = PVector.sub(desired, vel); steer.limit(maxforce); // Limit to maximum steering force acc.add(steer); } // Method to update location void update() { // Update velocity vel.add(acc); // Limit speed vel.limit(maxspeed); loc.add(vel); // Reset accelertion to 0 each cycle acc.mult(0); } void render() { // Draw a triangle rotated in the direction of velocity float theta = vel.heading2D() + PApplet.radians(90); fill(175); stroke(0); pushMatrix(); translate(loc.x,loc.y); rotate(theta); beginShape(PConstants.TRIANGLES); vertex(0, -r*2); vertex(-r, r*2); vertex(r, r*2); endShape(); popMatrix(); } // Wraparound void borders() { if (loc.x < -r) loc.x = width+r; if (loc.y < -r) loc.y = height+r; if (loc.x > width+r) loc.x = -r; if (loc.y > height+r) loc.y = -r; } }