int NUM_BOIDS = 100; int DIST_THRESHOLD1 = 10; int DIST_THRESHOLD2 = 20; int DIST_THRESHOLD3 = 30; float FACTOR_COHESION = 100; float FACTOR_SEPARATION = 10; float FACTOR_ALINGMENT = 10; float VELOCITY_LIMIT = 3; float TRAIL_SCALE = 2; float r1 = 1.0; // Cohesion: pull to center of flock float r2 = 0.8; // Separation: avoid bunching up float r3 = 0.1; // Alingment: match average flock speed Boid[] flock = new Boid[NUM_BOIDS]; PFont font; String msg = ""; void setup(){ size(500, 300); background(0); randomSeed(int(random(1,1000))); for(int i=0; i width){ xpos = 0; } if(ypos < 0){ ypos = height; } else if(ypos > height){ ypos = 0; } } void limitVelocity(){ float velocity = sqrt(sq(vx) + sq(vy)); if(velocity > VELOCITY_LIMIT){ vx = (vx/velocity)*VELOCITY_LIMIT; vy = (vy/velocity)*VELOCITY_LIMIT; } } // Cohesion void rule1(){ float len = 0; int count = 0; for(int i=0; i < NUM_BOIDS; ++i){ if(this != flock[i]){ len = dist(xpos, ypos, flock[i].xpos, flock[i].ypos); if(len > DIST_THRESHOLD2 && len < DIST_THRESHOLD3){ v1.x += flock[i].xpos; v1.y += flock[i].ypos; count++; } } } if(count > 0){ v1.x /= count; v1.y /= count; v1.x = (v1.x - xpos) / FACTOR_COHESION; v1.y = (v1.y - ypos) / FACTOR_COHESION; } } // Separation void rule2(){ float len = 0; for(int i=0; i < NUM_BOIDS; ++i){ if(this != flock[i]){ len = dist(xpos, ypos, flock[i].xpos, flock[i].ypos); if(len < DIST_THRESHOLD1){ v2.x -= (flock[i].xpos - xpos)/FACTOR_SEPARATION; v2.y -= (flock[i].ypos - ypos)/FACTOR_SEPARATION; } } } } // Alingment void rule3(){ float len = 0; int count = 0; for(int i=0; i < NUM_BOIDS; ++i){ if(this != flock[i]){ len = dist(xpos, ypos, flock[i].xpos, flock[i].ypos); if(len > DIST_THRESHOLD1 && len < DIST_THRESHOLD2){ v3.x += flock[i].vx; v3.y += flock[i].vy; count++; } } } if(count > 0){ v3.x /= count; v3.y /= count; v3.x = (v3.x - vx)/FACTOR_ALINGMENT; v3.y = (v3.y - vy)/FACTOR_ALINGMENT; } } } class Vector{ float x, y; public Vector(){ x = 0; y = 0; } public Vector(float inX, float inY){ x = inX; y = inY; } }