import java.util.ArrayList; import java.util.List; import processing.core.PApplet; import processing.core.PVector; /** * Flock of images based on tracked user movement. */ public class Flock extends Puppet { public List boids; public Flock(TrackedUser user, int sensorId) { // the desiredPosition of the flock should represent the center that they are trying to get to super(user, sensorId); boids = new ArrayList(); } @Override public void update(int deltaTime) { super.update(deltaTime); for (DynamicSceneImage boid : boids) { int count = 0; PVector steer = new PVector(); float boidHalfDistance = PApplet.sqrt(PApplet.sq((boid.image.width * boid.scale.x)) + PApplet.sq(boid.image.height * boid.scale.y)) * 0.5f; // separate the boids for (DynamicSceneImage otherBoid : boids) { float desiredSeparation = boidHalfDistance + PApplet.sqrt(PApplet.sq(otherBoid.image.width * otherBoid.scale.x) + PApplet.sq(otherBoid.image.height * otherBoid.scale.y)) * 0.5f; float distance = PVector.dist(boid.position, otherBoid.position); if (distance > 0 && !Util.areLike(distance, 0.0f) && distance < desiredSeparation) { PVector diff = PVector.sub(boid.position, otherBoid.position); diff.normalize(); diff.div(distance); steer.add(diff); count++; } } // avoid the parts of the tracked user for (PVector point : getAllUserPoints()) { float desiredSeparation = 75f + boidHalfDistance; float distance = PVector.dist(boid.position, point); if (distance > 0f && !Util.areLike(distance, 0.0f) && distance < desiredSeparation) { PVector diff = PVector.sub(boid.position, point); diff.normalize(); diff.div(distance); steer.add(diff); count++; } } if (count > 0) { steer.div((float) count); } if (steer.mag() > 0) { steer.normalize(); steer.mult(boid.maxSpeed); steer.sub(boid.velocity); steer.limit(boid.maxForce); } // also steer each point towards the tracked point PVector steerCenter = new PVector(); if (lastTrackedTimer > lastTrackedThreshhold) { // send off screen steerCenter.set(PVector.sub(defaultIdlePosition, boid.position)); } else { // find the closest tracked point and steer towards it PVector closest = new PVector(); float closestDistance = 10000f; for (PVector point : getAllTrackedPoints()) { float distance = PVector.dist(point, boid.position); if (distance < closestDistance) { closestDistance = distance; steerCenter = PVector.sub(point, boid.position); } } } if (steerCenter.mag() > 0) { steerCenter.normalize(); steerCenter.mult(boid.maxSpeed); steerCenter.sub(boid.velocity); steerCenter.limit(boid.maxForce); } // consider trying to avoid each tracked point to a certain distance? // arbitrarily weigh the forces steer.mult(1.5f); steerCenter.mult(1.0f); // apply forces boid.applyForce(steer); boid.applyForce(steerCenter); boid.update(deltaTime); } } @Override public void render() { for (DynamicSceneImage boid : boids) { boid.render(); } } }