Nature of Code Midterm Project

I decided to use the creature I designed in previous assignments, to develop an ecosystem of two different species living together inside of a water tank. There is a particle system of small creatures (boids) flocking together, and a larger creature (predator) that follows and repels them as they “swim”.
The object “predator” is an extension of the object “boid”, so that they all have the same swimming behaviors but with different values according to their size.




Processing code:

ArrayList boids = new ArrayList(); // array of boids Predator predator; // predator class PVector mouse; // mouse vector int boidNum = 100; // initial number of boids float repelRad = 60; // size of repeller force float timer; // timer for oscillation void setup() { frameRate(30); size(800, 800, P2D); // create boids for (int i=0; i boids) { avoidForce(boids); approachForce(boids); alignForce(boids); } void update() { // Calculate and add next position (by K) PVector nextPos = loc; nextPos.add(vel); // Calculate distance from the center of screen PVector center = new PVector(width/2, height/2); float dist = nextPos.dist(center); // Check edges and bounce according to distance if (dist >= height/2) { vel.x = vel.x * -mass; vel.y = vel.y * -mass; } vel.add(acc); loc.add(vel); acc.mult(0); // reset acc every time update is called vel.limit(4); // limit on speed } void applyF(PVector force) { //F=ma force.div(mass); acc.add(force); } void display() { update(); noStroke(); fill(255, 200); ellipse(loc.x, loc.y, mass, mass); } // AVOID void avoidForce(ArrayList boids) { float count = 0; // keep track of how many boids are close PVector locSum = new PVector(); // store positions for (Boid other : boids) { int separation = mass + 25; // separation, using mass as reference PVector dist = PVector.sub(other.getLoc(), loc); // distance to other boid float d = dist.mag(); if (d != 0 && d0) { locSum.div(count); // divide by number of other positions PVector avoidVec = PVector.sub(loc, locSum); avoidVec.limit(maxForce*3); // Avoid border of circle (math by K) PVector center = new PVector(width/2, height/2); float dist = loc.dist(center); float reduce = dist / (width/2); // 0..1 PVector avoidBorder = new PVector(center.x, center.y); avoidBorder.sub(loc); avoidBorder.normalize(); avoidBorder.mult(reduce * 5); avoidVec.add(avoidBorder); applyF(avoidVec); } } // APPROACH void approachForce(ArrayList boids) { float count = 0; // keep track of how many boids are close PVector locSum = new PVector(); // store locations for (Boid other : boids) { int approachRadius = mass + 40; // radius of distance between boids PVector dist = PVector.sub(other.getLoc(), loc); float d = dist.mag(); if (d != 0 && d0) { locSum.div(count); // divide by number of other positions PVector approachVec = PVector.sub(locSum, loc); approachVec.limit(maxForce); applyF(approachVec); } } // ALIGN void alignForce(ArrayList boids) { float count = 0; // keep track of how many boids are close PVector velSum = new PVector(); // store velocities for (Boid other : boids) { int alignRadius = mass + 100; // radius of distance between boids PVector dist = PVector.sub(other.getLoc(), loc); float d = dist.mag(); if (d != 0 && d0) { velSum.div(count); // divide by number of other positions PVector alignVec = velSum; alignVec.limit(maxForce); applyF(alignVec); } } // REPEL (NEW!!) void repelForce(PVector repeller, float radius) { PVector futPos = PVector.add(loc, vel); // calculate future position PVector dist = PVector.sub(repeller, futPos); float d = dist.mag(); if (d <= radius) { PVector repelVec = PVector.sub(loc, repeller); repelVec.normalize(); if (d != 0) { float scale = 1.0/d; // stronger if boid is closer to the repeller repelVec.normalize(); repelVec.mult(maxForce*7); if (repelVec.mag()<0) { // avoid the repeller repelVec.y = 0; } } applyF(repelVec); } } // Get acces loc and vel for any boid. PVector getLoc() { return loc; } PVector getVel() { return vel; } } class Predator extends Boid { // Predator is a child of Boid int maxForce = 10; // higher effect of the force // Constructor Predator(PVector _loc, int scope) { super(_loc); mass = 30; } void display() { update(); fill(255, 150); noStroke(); float theta = vel.heading2D(); // angle for oscillation // Body ellipse(loc.x, loc.y, mass, mass); ellipse(loc.x, loc.y, mass*.8, mass*.8); // Legs pushMatrix(); translate(loc.x, loc.y); rotate(theta); stroke(255, 200); strokeWeight(4); displayLeg(mass * 0.75, 0.75, 0.3); displayLeg(mass * 0.75, 0.25, 0.1); displayLeg(mass * 0.75, -0.25, -0.1); displayLeg(mass * 0.75, -0.75, -0.3); popMatrix(); } // Leg functionality void displayLeg(float length, float angle, float delay) { float rotation = 0.5 * sin(3 * (timer - delay)); float leftAngle = angle + rotation; float rightAngle = PI - angle - rotation; line(0, 0, length * sin(leftAngle), length * cos(leftAngle)); line(0, 0, length * sin(rightAngle), length * cos(rightAngle)); } void update() { // Calculate distance from the center of screen PVector center = new PVector(width/2, height/2); float dist = loc.dist(center); // Check edges and bounce according to distance if (dist >= height/2 -mass) { vel.x = vel.x * -mass/4; vel.y = vel.y * -mass/4; } vel.add(acc); loc.add(vel); acc.mult(0); vel.limit(6); // higher speed limit } // APPROACH to follow Boids void approachForce(ArrayList boids) { float count = 0; // keep track of how many boids are close PVector locSum = new PVector(); // store locations for (Boid other : boids) { int approachRadius = mass + 300; // radius of distance from boids, higher PVector dist = PVector.sub(other.getLoc(), loc); float d = dist.mag(); if (d != 0 && d0) { locSum.div(count); // divide by number of other positions PVector approachVec = PVector.sub(locSum, loc); approachVec.limit(maxForce); applyF(approachVec); } } }

Leave a Reply