Simulating flocking behavior with boids

(0.0.0) - Background

Craig Reynolds published the boids algorithm in 1987. Three rules, each operating on a single agent using only local information:

  1. Separation — steer away from neighbors that are too close
  2. Alignment — steer toward the average heading of nearby neighbors
  3. Cohesion — steer toward the average position of nearby neighbors

That’s it. Three forces, linearly combined. And from this you get flocking, schooling, herding — the kind of coordinated group motion that looks like it requires a leader or a plan but requires neither.

(1.0.0) - Implementation

I built this in vanilla JavaScript with Canvas 2D. Each boid is an object with position, velocity, and acceleration vectors. Every frame:

  1. For each boid, find all neighbors within a perception radius
  2. Compute the three steering forces
  3. Weight and sum them
  4. Apply to acceleration, then velocity, then position
  5. Wrap around screen edges

The naive approach is O(n²) per frame (every boid checks every other boid). For 500 boids at 60fps, that’s 15 million distance checks per second. It works, but barely. Adding a spatial hash grid brought it down to effectively O(n) and let me run 2,000 boids smoothly.

The interesting part

What fascinates me about boids isn’t the algorithm — it’s the gap between the rules and the behavior. You read the three rules and think “okay, that’s straightforward.” Then you run it and see a flock split around an obstacle and rejoin on the other side and you think “wait, I didn’t program that.” You didn’t. It emerged.

This is the core of complexity science: simple local rules producing global patterns that no individual agent is aware of. It’s ants finding shortest paths. It’s traffic jams propagating backward through traffic. It’s neurons producing consciousness (maybe).

Knobs

The fun part is tuning the weights. Heavy separation and low cohesion gives you scattered particles that avoid each other like commuters on a train. High cohesion and low separation gives you a tight swarm that moves as a blob. The sweet spot — the one that looks like real starlings — is surprisingly narrow.

I added a predator that the boids flee from. The evasion patterns are eerily realistic without any predator-specific code. The boids just see a fast-moving neighbor that’s too close and their separation rule fires harder. The flock parts, reforms, creates vortices. All from three rules and a scary dot.