For Unit 1 of CSCI 5611:F20, I decided to create a procedural system that mimics the flocking behavior of sheep being herded by a herd dog. The goal is to be able to herd every single sheep into the pen/enclosure in the middle of the screen, however, there is only one way in!
In this flocking simulation, the sheep have a high tendency to flock together. I wanted to mimic videos I've seen before such as this and this, so as the simulation continues you will see high cohesion between all the sheep.
The herding dog is a sprite that was modeled directly after a Minecraft dog's face, and the sheep after Minecraft sheep's face. The middle box is an enclosure with the goal of herding the sheep into the enclosure through the bottom entrance. The forces are forgiving enough that some sheep will find their way into the enclosure, but most won't go in without a little help from the user.
The user has control of a herding dog sprite via the position of your mouse. Whenever the sheep are too close to the dog, they will temporarily increase their speed to get away and will actively avoid the area around the dog. Users will herd the sheep into the centered enclosure. If the user wants more sheep, they simply have to hold the left mouse button down to create more sheep.
There are 5 obstacles the are stationary: the enclosure and 4 posts, one in each corner. There is also a dynamically controlled obstacle: the herding dog. These forces only interact when sheep are within the obstacles area of effect.
Each boid object is rendered with a pixelated sheep face that rotate with the velocity vector's direction. This similar rendering can be seen with the herding dog as well.
Calculated average fps and total boid objects can be found in the code repository in average_framerate_calc.txt. The fps is the first value which is 37.468422, and the total boid ending objects is 1074. Initially there are 1100 boids rendered to begin with. To test performance, run the program and press "s" on your keyboard to save a new average_framerate_calc.txt with the average fps and the ending boid object count.
Time - Feature
0:00 - Flocking
0:13 - Simulation context
0:32 - User interaction
1:01 - Obstacle avoidance
1:32 - Improved Boid Rendering
For the most part everything was fairly simply to implement. The problem I had for a long time was that when I would add sheep by clicking the mouse, all the sheep on the screen would vanish! Using the debugger tool in Processing3, I found that my code was setting every vector (position, velocity, acceleration) to NaN. I wish the debugger would print the variables by default upon error, but eventually I found out that Vec2.normalize() would return NaN. This was really weird, until I tried normalizing a zero vector. normalizer() is calculated by
float magnitude = sqrt(x*x + y*y);
x /= magnitude;
y /= magnitude;
and if x and y are 0, then we are dividing 0 by 0 resulting in NaN. I fixed this by adding a simple check to return a zero vector if magnitude is 0.
float magnitude = sqrt(x*x + y*y);
if (Float.isNaN(magnitude) || magnitude == 0){
x = 0;
y = 0;
}
else{
x /= magnitude;
y /= magnitude;
}
Code for Boid flocking objects based on code provided by CSCI 5611 here.
Further inspiration was found by analyzing an object oriented approach to flocking from Processing's website examples.
Minecraft is a registered trademark of Mojang Synergies AB and my representations of Minecraft's sheep and dogs are in no way a result of my own creative design. You can purchase or learn more about minecraft here.