1,400 silver sardines mill, stream and pack into a bait ball as dolphins close in.
Each sardine follows Couzin's zone model: it turns at a limited rate away from any fish inside its zone of repulsion, otherwise toward a blend of its neighbors' headings (zone of orientation) and positions (zone of attraction), ignoring the blind wedge behind it. Widening only the orientation zone moves the school through its known collective states, from swarm to milling torus to dynamic and highly parallel groups, while a few informed fish lead the parallel ones, and the polarization and milling order parameters are plotted live. The school is a thin 3D slab, so fish can slip past in front of and behind each other, and a spatial grid with cell-level centers of mass keeps neighbor sums fast. When dolphins hunt, fear spreads from fish to fish, the zones shrink and the school packs into a spinning bait ball that flashes as fish bank and tilt their silver flanks toward the sun shafts.
Try it. Move the pointer to become a dolphin and herd or split the school; click to startle it into a flash expansion. The buttons (or keys 1 to 4) pick swarm, torus, dynamic parallel or highly parallel; Auto (A) tours them and brings in a pair of hunting dolphins.
Paste this into Claude Code, Codex or any coding agent to get a simple version running, then take it wherever you like.
Build a fish school simulation with JavaScript and the HTML canvas element, using Couzin's zone model of collective motion. Put everything in a single index.html file with no libraries or build step, so I can open it directly in a browser.
Start simple:
- Make a full-window canvas that stays sharp on high-DPI screens. Fill it with a vertical gradient from bright blue to deep navy, like open water seen from the side.
- Create 400 fish with a position and a heading angle. Each fish swims at a constant speed and can only turn at a limited rate (about 1 to 2 radians per second).
- Every frame, each fish looks at its neighbors in three zones. If anyone is closer than one body length (repulsion), it turns away from them and ignores everything else. Otherwise it averages the headings of fish within a few body lengths (orientation) and the directions toward fish farther out, up to about 10 body lengths (attraction), and turns toward the combination. Ignore fish in a blind wedge directly behind it.
- Use a simple grid to find neighbors quickly, and steer fish gently back from the edges.
- Draw each fish as a small tapered silhouette pointing along its heading.
Once that works, make it beautiful:
- Add keys that change only the width of the orientation zone, and watch the school switch between a swarm, a milling torus and a parallel group. Print the polarization (length of the average heading) and the milling order (average angular momentum about the center) on screen.
- Make the fish silver: brighten a fish when it is turning hard, as if it banked and caught the sun, so flashes ripple across the school. Add a few slanted light shafts from the surface.
- Let the mouse be a predator that fish flee, with panic spreading to neighbors.
Explain the key ideas in short code comments. When you're done, tell me how to open it and suggest three directions I could take it next, such as a dolphin that circles the school to herd it into a bait ball, a few informed fish that lead the group somewhere, or a thin 3D slab so fish can pass in front of each other.