A while back , I wrote an article about Boids , a flocking algorithm. I didn’t actually implement it at the time; I just talked about it. Now I have some ideas for using it to create some interesting art, so I thought I’d implement it in Rust and Nannou.
There many examples of Boids implementations on the internet. Mine is a straightforward translation of Ben Eater's javascript example into Rust. Here, we are creating 50 “boid” objects, in random positions around the screen and moving at random speeds in random directions. As they pass close enough to “see” each other, they will tend to cluster into flocks. Each boid is a different color to make it easier to track individual ones while watching the app running.
You may recall that three are three rules of movement for boids: they steer towards the center of mass of their neighbors, they steer to avoid overcrowding their neighbors, and they steer towards the average direction of their neighbors. By “neighbors” here, I mean just the nearby boids; they can only “see” each other up to a certain distance away. Two other constraints here are that they steer to stay on the canvas, and they have a maximum speed limit. Of course, all the other boids are trying to follow the same rules, so together they develop some interesting random-ish flocking behavior!
As I mentioned, my code is a translation of Ben Eater's code into Rust. It was fairly easy to make this change, but I was hung up for a while on one issue. My boids weren’t flocking as expected; they were clustering into crystalline structures and just vibrating. I looked for quite a while at my algorithm trying to figure out what error I had made. The problem turned out to be not the algorithm at all. I had set the speed limit too low! The boids have to be able to develop enough speed to swoop into areas where they are not supposed to be, for example, too close to another boid, so that the rules have a chance to steer them back to where they should be (which they will also overshoot, possibly getting them close enough to other boids to make them their neighbors, etc).
This video shows the app running. All the boids are randomly placed on the canvas, and as they notice their neighbors, they start to form flocks. Notice that as a flock gets larger, it may split. Two flocks passing near each other will influence each other: if going in a similar direction, some of all boids from one may join the other. Or the direction of one or both flocks may change. If the flocks are moving quickly in opposite directions, they may be little effect on either, as none of the boid remain “neighbors” long enough to affect each other.
This app looks more impressive with a larger number of boids on a larger canvas. Of course, that starts ramping up the computing power necessary for it to run smoothly. On mine, with the app compiled for release (cargo build --release
), I am able to display and update a 1000 boids seamlessly. With 10,000 boids, it is noticably jerky. Your mileage may vary.
My boids source code is on Gitlab .
In the future, I plan to try to generate something more interesting using the boids algorithm as a basis. Stay tuned!