I am trying to implement a flocking boids program based on Cornrad Prkers' algorithm. I seem to be having problems with summing up all the forces (alignment, cohesion and separation). I keep getting a weird behavior.
The alignment part of the algorithm is responsible for velocity matching.
public Point alignment(Boids boid){
double xVelocity = 0;
double yVelocity = 0;
ArrayList<Boids> neighborhood = new ArrayList<Boids>();
neighborhood = neighborHood(boid, Boids.DetectionRange);
if(neighborhood.size() > 1){
for(int i = 0; i < neighborhood.size(); i++){
Boids otherBoid = neighborhood.get(i);
if(boid != otherBoid){
xVelocity += otherBoid.velocity.x;
yVelocity += otherBoid.velocity.y;
}
}
xVelocity /= neighborhood.size();
yVelocity /= neighborhood.size();
}
else{
return new Point(0, 0);
}
return new Point((int)xVelocity, (int)yVelocity);
}
the separation is responsible for collsion avoidance
public Point sepration(Boids boid){
double xPosition = boid.location.x;
double yPosition = boid.location.y;
double xDistance = 0;
double yDistance = 0;
ArrayList<Boids> neighborhood = new ArrayList<Boids>();
neighborhood = neighborHood(boid, Boids.SeperationRange);
if (neighborhood.size() > 1){
for(int i = 0; i < neighborhood.size(); i++){
Boids otherBoid = this.get(i);
if(boid != otherBoid){
xDistance = (int) (boid.location.x - otherBoid.location.x);
yDistance = (int) (boid.location.y - otherBoid.location.y);
if(boid.checkCollision(otherBoid.getLocation())){
if(xDistance > 0 && xDistance < Boids.SeperationRange){
xPosition -= xDistance;
}
if(yDistance > 0 && yDistance < Boids.SeperationRange){
yPosition -= yDistance;
}
}
}
}
}else{
return new Point(0,0);
}
xPosition /= neighborhood.size();
yPosition /= neighborhood.size();
return new Point((int)xPosition, (int)yPosition);
}
the cohesion is responsible for the flocking behavior, boids are attracted to each other as long as they are within their detection range.
public Point cohesion(Boids boid){
int x = 0;
int y = 0;
ArrayList<Boids> neighborhood = new ArrayList<Boids>();
neighborhood = neighborHood(boid, Boids.DetectionRange);
if (neighborhood.size() > 0){
for(int i = 0; i < neighborhood.size(); i++){
Boids otherBoid = neighborhood.get(i);
if(boid != otherBoid){
x += otherBoid.location.x;
y += otherBoid.location.y;
}
x /= neighborhood.size();
y /= neighborhood.size();
}
}else{
return new Point(0 , 0); // empty vector
}
return new Point(x, y);
}
Each of the steering behavior returns a vector (Point in Java), which I then normalize and then apply a weighted force of the unit vector, to move it one unit to its target point.