// 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 MyShape aMan; int asize; int acolor=0; Boid(PVector l, float ms, float mf,int ac, int as) { loc = l.get(); r = 3.0f; maxspeed = ms; maxforce = mf; acolor=ac; if (as==0) { aMan = new Man2(); } else { aMan = new Man(); } 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); //return 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); float theta = 0; fill(175); stroke(acolor); pushMatrix(); translate(loc.x,loc.y); rotate(theta); // beginShape(PConstants.TRIANGLES); // vertex(0, -r*2); // vertex(-r, r*2); // vertex(r, r*2); // endShape(); aMan.render(); 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; } }