Reynolds boids (using Look Compute Move)

This example explains how to implement Craig Reynold's Boids [1] in JBotSim. The purpose is to simulate bird flocks. There is no global behavior implemented because the flock behavior emerge from three rules. We use the boids pseudocode written by Conrad Parker [2]. The position of a boid in round i is determined by the position and speed of its neighbors in round i-1.

You can download an executable JAR that contains the source code and a copy of JBotSim.
(Run by typing `java -jar boids.jar`.)

Timing

In JBotSim, we redefine the following methods: `onPreClock`, `onClock` and `onPostClock`. We have the guarantee that `onPreClock` will first executes on all the boids before `onClock` is executed, and same between `onClock` and `onPostClock`. Hence, all the boids first find their neighbors, then they compute the next location, then apply the resulting movement.

``````
@Override // Look around
public void onPreClock(){
theNeighbors.clear();
List<Node> sensedNode = getSensedNodes();
for (Node aNode : sensedNode){
if (aNode instanceof Boid)
}
}

@Override // Compute movement
public void onClock(){
nextVelocity = velocity;
nextVelocityMax(); // Animal limitation
}

@Override // Move
public void onPostClock(){
Point target = new Point();
velocity = nextVelocity;
target.setLocation(getLocation().getX()+velocity.getX(),
getLocation().getY()+velocity.getY());
setDirection(target);
move(velocity.distance());
wrapLocation();
}
``````

Each boid has three rules:

• Cohesion: remain grouped
• Alignment: keep the average direction of the group
• Separation: avoid collision with other boids

We also add a method to limit the speed of the boids.

``````public Vector2D groupFlock(){
Vector2D center = new Vector2D();
for (Boid aBoid : theNeighbors) {
if(!aBoid.equals(this)) {
}
}
if (theNeighbors.size()>0){
center.division(theNeighbors.size());
center.substract(getLocation().getX(),getLocation().getY());
center.division(1000.);
}
return center;
}

public Vector2D collisionAvoidance(){
Vector2D avoid = new Vector2D();
for (Boid aBoid : theNeighbors) {
if(!aBoid.equals(this)) {
if(distance(aBoid)<60){
Vector2D tempDistance = new Vector2D(
aBoid.getLocation().getX()-getLocation().getX(),
aBoid.getLocation().getY()-getLocation().getY());
avoid.substract(tempDistance);
}
}
}
avoid.division(20.);
return avoid;
}

public Vector2D matchVelocity(){
Vector2D global = new Vector2D();
for (Boid aBoid : theNeighbors) {
if(!aBoid.equals(this)) {