Processing Forum
Flock flock;
void setup() {size(640, 360);flock = new Flock();// Add an initial set of boids into the systemfor (int i = 0; i < 250; i++) {flock.addBoid(new Boid(new PVector(width/2,height/2), 3.0, 0.05));}smooth();}
void draw() {background(255);flock.run();}
// Add a new boid into the Systemvoid mousePressed() {flock.addBoid(new Boid(new PVector(mouseX,mouseY),23.0f,0.05f));}
// The Boid class
class Boid {
PVector loc;PVector vel;PVector acc;float r;float maxforce; // Maximum steering forcefloat maxspeed; // Maximum speed
Boid(PVector l, float ms, float mf) {acc = new PVector(0,0);vel = new PVector(random(-.5,.5),random(-.5,.5));loc = l.get();r = 4;maxspeed = ms;maxforce = mf;}
void run(ArrayList boids) {flock(boids);update();borders();render();}
// We accumulate a new acceleration each time based on three rulesvoid flock(ArrayList boids) {PVector sep = separate(boids); // SeparationPVector ali = align(boids); // AlignmentPVector coh = cohesion(boids); // Cohesion// Arbitrarily weight these forcessep.mult(1.5);ali.mult(1.0);coh.mult(1.0);// Add the force vectors to accelerationacc.add(sep);acc.add(ali);acc.add(coh);}
// Method to update locationvoid update() {// Update velocityvel.add(acc);// Limit speedvel.limit(maxspeed);loc.add(vel);// Reset accelertion to 0 each cycleacc.mult(0);
}
void seek(PVector target) {acc.add(steer(target,false));}
void arrive(PVector target) {acc.add(steer(target,true));}
// A method that calculates a steering vector towards a target// Takes a second argument, if true, it slows down as it approaches the targetPVector steer(PVector target, boolean slowdown) {PVector steer; // The steering vectorPVector desired = target.sub(target,loc); // A vector pointing from the location to the targetfloat d = desired.mag(); // Distance from the target is the magnitude of the vector// If the distance is greater than 0, calc steering (otherwise return zero vector)if (d > 0) {// Normalize desireddesired.normalize();// Two options for desired vector magnitude (1 -- based on distance, 2 -- maxspeed)if ((slowdown) && (d < 100.0)) desired.mult(maxspeed*(d/100.0)); // This damping is somewhat arbitraryelse desired.mult(maxspeed);// Steering = Desired minus Velocitysteer = target.sub(desired,vel);steer.limit(maxforce); // Limit to maximum steering force}else {steer = new PVector(0,0);}return steer;}
void render() {// Draw a triangle rotated in the direction of velocityfloat theta = vel.heading2D() + PI/2;fill(100,100,100,100);//stroke(1); //255//strokeWeight(1);pushMatrix();translate(loc.x,loc.y);rotate(theta);ellipse(0, 0, .5, .5);// point (loc.x,loc.y);popMatrix();}
// Wraparoundvoid 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;}
// Separation// Method checks for nearby boids and steers awayPVector separate (ArrayList boids) {float desiredseparation = 20.0;PVector steer = new PVector(0,0,0);int count = 0;// For every boid in the system, check if it's too closefor (int i = 0 ; i < boids.size(); i++) {Boid other = (Boid) boids.get(i);float d = PVector.dist(loc,other.loc);// If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)if ((d > 0) && (d < desiredseparation)) {// Calculate vector pointing away from neighborPVector diff = PVector.sub(loc,other.loc);diff.normalize();diff.div(d); // Weight by distancesteer.add(diff);count++; // Keep track of how many}}// Average -- divide by how manyif (count > 0) {steer.div((float)count);}
// As long as the vector is greater than 0if (steer.mag() > 0) {// Implement Reynolds: Steering = Desired - Velocitysteer.normalize();steer.mult(maxspeed);steer.sub(vel);steer.limit(maxforce);}return steer;}
// Alignment// For every nearby boid in the system, calculate the average velocityPVector align (ArrayList boids) {float neighbordist = 25.0;PVector steer = new PVector(0,0,0);int count = 0;for (int i = 0 ; i < boids.size(); i++) {Boid other = (Boid) boids.get(i);float d = PVector.dist(loc,other.loc);if ((d > 0) && (d < neighbordist)) {steer.add(other.vel);count++;}}if (count > 0) {steer.div((float)count);}
// As long as the vector is greater than 0if (steer.mag() > 0) {// Implement Reynolds: Steering = Desired - Velocitysteer.normalize();steer.mult(maxspeed);steer.sub(vel);steer.limit(maxforce);}return steer;}
// Cohesion// For the average location (i.e. center) of all nearby boids, calculate steering vector towards that locationPVector cohesion (ArrayList boids) {float neighbordist = 25.0;PVector sum = new PVector(0,0); // Start with empty vector to accumulate all locationsint count = 0;for (int i = 0 ; i < boids.size(); i++) {Boid other = (Boid) boids.get(i);float d = loc.dist(other.loc);if ((d > 0) && (d < neighbordist)) {sum.add(other.loc); // Add locationcount++;}}if (count > 0) {sum.div((float)count);return steer(sum,false); // Steer towards the location}return sum;}}
// The Flock (a list of Boid objects)
class Flock {ArrayList boids; // An arraylist for all the boids
Flock() {boids = new ArrayList(); // Initialize the arraylist}
void run() {for (int i = 0; i < boids.size(); i++) {Boid b = (Boid) boids.get(i);b.run(boids); // Passing the entire list of boids to each boid individually}}
void addBoid(Boid b) {boids.add(b);}
}