hodgin_iquilezles · BoidsFlock
Boids Flock (Hodgin Murmuration)
A 2D flock of boids steered by Craig Reynolds' three classic rules (separation, alignment, cohesion) over a coarse spatial-hash neighbor query. A weak long-range goal force tugs the flock across the canvas. Particles trace a low-alpha stroke buffer, producing Hodgin's swooping, ever-coalescing silhouettes.
Original: https://roberthodgin.com/project/murmuration
▶ Try the live demo (JS port) ▶ Run reference.py via Pyodide 10 formulas have instant JS ports. The Pyodide path runs the actual Python in your browser — first load is ~6 MB, then instant.
Math essence
For each boid i, accumulate weighted sums of separation (1/r^2 push inside separation_radius), alignment (mean velocity inside neighbor_radius), and cohesion (mean position inside neighbor_radius), using a uniform spatial hash for O(num) total work. A weak goal-toward-vector adds a small acceleration. Total acceleration is clamped to max_force, integrated into velocity (clamped to max_speed) and position. The previous-to-current position segment is stroked onto a decaying canvas.
Parameters
| Name | Type | Default | Range | Description |
|---|---|---|---|---|
dim | int | 500 | 200–1000 | Square canvas side length in pixels. |
num | int | 250 | 60–1500 | Number of boids. |
neighbor_radius | float | 32 | 10–80 | Radius (px) inside which a boid considers neighbours for align/coh/sep. |
separation_radius | float | 14 | 4–40 | Inner radius (px) within which separation dominates. |
w_sep | float | 1.6 | 0–4 | Separation weight. |
w_align | float | 1 | 0–3 | Alignment weight. |
w_coh | float | 0.9 | 0–3 | Cohesion weight. |
w_goal | float | 0.04 | 0–0.3 | Migration-goal weight. |
max_speed | float | 3.2 | 0.5–8 | Speed clamp (px/frame). |
max_force | float | 0.18 | 0.02–0.6 | Acceleration clamp (px/frame^2). |
trail_decay | float | 0.965 | 0.85–0.999 | Per-frame multiplicative fade of the canvas. |
Reference
First 60 lines of reference.py. Full source:
library_external/hodgin_iquilezles/BoidsFlock/reference.py
from __future__ import annotations
from typing import ClassVar
import numpy as np
class BoidsFlock:
"""Boids Flock — Robert Hodgin (flight404), circa 2003–2024.
A 2D Reynolds-style boids simulation in the spirit of Hodgin's
*Murmuration* / "Bird Migration" series (roberthodgin.com/project/murmuration).
Each boid obeys three classic Reynolds rules — *separation*, *alignment*,
*cohesion* — applied to all neighbours inside ``neighbor_radius``.
A weak long-range "migration" force tugs the flock toward ``goal``,
yielding the swooping, ever-coalescing silhouettes Hodgin is known for.
Particles trace a low-alpha stroke from their previous to their current
position; the accumulated frame buffer is the rendered image. The
algorithm uses a coarse spatial hash so that ~200–1000 boids run in
near-realtime even on pure NumPy.
"""
family: ClassVar[str] = "hodgin_iquilezles"
sketch: ClassVar[str] = "boidsflock"
def __init__(
self,
dim: int = 500,
num: int = 250,
neighbor_radius: float = 32.0,
separation_radius: float = 14.0,
w_sep: float = 1.6,
w_align: float = 1.0,
w_coh: float = 0.9,
w_goal: float = 0.04,
max_speed: float = 3.2,
max_force: float = 0.18,
trail_decay: float = 0.965,
ink_color: tuple[int, int, int] = (240, 245, 255),
background: tuple[int, int, int] = (8, 8, 14),
**_,
) -> None:
self.dim = dim
self.num = num
self.neighbor_radius = neighbor_radius
self.separation_radius = separation_radius
self.w_sep = w_sep
self.w_align = w_align
self.w_coh = w_coh
self.w_goal = w_goal
self.max_speed = max_speed
self.max_force = max_force
self.trail_decay = trail_decay
self.ink_color = np.array(ink_color, dtype=np.float32)
self.bg_color = np.array(background, dtype=np.float32)
self.reset()
def reset(self, seed: int | None = None) -> None:
self.rng = np.random.default_rng(seed) Try running it locally
The reference implementation is self-contained Python with numpy. Install the package and run:
python library_external/hodgin_iquilezles/BoidsFlock/reference.py Need help? See Learn for the standard environment setup, or Playground for an in-browser sketchbook.
More from hodgin × iquilezles
Fractional Brownian Motion noise
hodgin_iquilezles · FBMNoise
Quilez's canonical fBM: a 2D value-noise base summed over N octaves whose frequency doubles and amplitude is multiplied by G = exp2(-H) per octave.
Magneto Particles (Hodgin Magnetosphere)
hodgin_iquilezles · MagnetoParticles
Particles pulled and pushed by N orbiting magnetic anchors whose charges flip sign over time.
Mulberry32 PRNG (stratified scatter)
hodgin_iquilezles · Mulberry32RNG
Mulberry32 is a tiny 32-bit-state pseudo-random number generator popularised in the demoscene and used pervasively by Quilez and other graphics programmers as the RNG inside procedural sketches.
Saturn Rings (orbital resonance)
hodgin_iquilezles · SaturnRings
Thousands of particles are initialized in an annulus between inner_radius and outer_radius around a central mass, with circular orbital velocities v = sqrt(M/r).
Smooth-Minimum SDF field
hodgin_iquilezles · SmoothMinSDF
Two animated 2D SDF primitives (a moving circle and a translating slab) are blended with Quilez's quadratic-polynomial smooth-minimum and rendered as a scalar field.
Worley / Cellular Noise
hodgin_iquilezles · WorleyNoise
Quilez's classic 2D Worley noise: a unit grid of cells, each containing one pseudo-random feature point placed by a 2D integer hash.