// Based on examples in Nature of Code by Daniel Shiffman // A list of vehicles ArrayList<Vehicle> vehicles; void setup() { size(1000, 1000); smooth(); // We are now making random vehicles and storing them in an ArrayList vehicles = new ArrayList<Vehicle>(); background(0); for (int i = 0; i < 50; i++) { float angle = map(i, 0, 50, 0, TWO_PI); vehicles.add(new Vehicle((cos(angle)*(width/5))+width/2, (sin(angle)*(width/ 5))+height/2)); } } void draw() { //background(0); fill(0, 20); rect(0, 0, width, height); if (vehicles.size() < 5000) { for (int i = 0; i < 50; i++) { float angle = map(i, 0, 50, 0, TWO_PI); vehicles.add(new Vehicle((cos(angle)*(width/5))+width/2, (sin(angle)*(widt h/5))+height/2)); } } for (Vehicle v : vehicles) { // Path following and separation are worked on in this function v.separate(vehicles); // Call the generic run method (update, borders, display, etc.) v.update(); //v.borders(); //v.display(); for (Vehicle vv : vehicles) {
if (dist(v.xpos(), v.ypos(), vv.xpos(), vv.ypos()) < width/20) {
stroke(255, map(dist(v.xpos(), v.ypos(), vv.xpos(), vv.ypos()), 0, width /20, 5, 0)); line(v.xpos(), v.ypos(), vv.xpos(), vv.ypos()); } } } for (int i = 0; i < vehicles.size (); i++) { Vehicle v = vehicles.get(i); if (v.isAlive == false) { vehicles.remove(i); } } } // Separation // Daniel Shiffman <http://www.shiffman.net> // The Nature of Code, 2011 // Vehicle class class Vehicle { // All the usual stuff PVector location; PVector velocity; PVector acceleration; float r; float maxforce; // Maximum steering force float maxspeed; // Maximum speed float life = 255; boolean isAlive = true; // Constructor initialize all values Vehicle(float x, float y) { location = new PVector(x, y); r = 12*4; maxspeed = 3; maxforce = 0.2; acceleration = new PVector(0, 0); velocity = new PVector(0, 0); } void applyForce(PVector force) { // We could add mass here if we want A = F / M acceleration.add(force); } // Separation // Method checks for nearby vehicles and steers away void separate (ArrayList<Vehicle> vehicles) { float desiredseparation = r*2; PVector sum = new PVector(); int count = 0; // For every boid in the system, check if it's too close for (Vehicle other : vehicles) { float d = PVector.dist(location, other.location); // 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 neighbor
PVector diff = PVector.sub(location, other.location); diff.normalize(); diff.div(d); // Weight by distance sum.add(diff); count++; // Keep track of how many } } // Average -- divide by how many if (count > 0) { sum.div(count); // Our desired vector is the average scaled to maximum speed sum.normalize(); sum.mult(maxspeed); // Implement Reynolds: Steering = Desired - Velocity PVector steer = PVector.sub(sum, velocity); steer.limit(maxforce); applyForce(steer); } }
// Method to update location
void update() { // Update velocity velocity.add(acceleration); // Limit speed velocity.limit(maxspeed); location.add(velocity); // Reset accelertion to 0 each cycle acceleration.mult(0); life -= 1; if (life < 0) { isAlive = false; } } void display() { fill(255); stroke(0); noStroke(); pushMatrix(); translate(location.x, location.y); ellipse(0, 0, r, r); popMatrix(); } // Wraparound void borders() { if (location.x if (location.y if (location.x if (location.y }