Boid World — Field Guide

pics-anim-pi-pixi.html · a field guide

The Boid World

One HTML file holds a complete small society — birth and death, courtship and divorce, heredity, epidemics, predators — and a WebGL pipeline that paints it, now with depth. This page maps both.

Part one

The world model

World model · Life cycle

Every boid is mortal

A boid fades in over 1.5 s with a birth ring, spends its youth dim and infertile, matures into a full-brightness adult, and ages under a Gompertz hazard whose modal age tracks population pressure. Three other doors lead to the same exit.

modal age 80 s × pressure (×0.4–1.25) hard cap 100 s hazard Gompertz, β = 3/mode inbreeding ×1–1.5 · small population extra hazard death 2 s fade + splash, partner widowed

World model · Courtship & pair bonds

Marriage by collision

Bonds form by literally bumping into the right stranger. Every touch within two radii counts as a hit; the odds of a hit landing are shaped by colour-family preference and by morphology — females favour long beaks, males favour big eyes. Enough hits and the pair bonds, glows, and starts a family.

singles 20% — never bond, drawn 0.7× gay 10% — same-sex bonds, no offspring bond after ≥1 hit (slider) family target ≈ N(4, 0.8) children divorce 5% per s — or drift past split dist no offspring beyond breed dist reel-in ramp reels strays back before they split no parent–child or sibling pairs

World model · Population regulation

Three arms, one thermostat

Every frame the tank takes its own census. Crowding above the target raises pressure; pressure pushes back through three independent arms — all negative feedback, so the population orbits the target instead of exploding or collapsing.

Arm 1 is also what draws the flock together. It pulls each boid toward its local centre with a conservative spring (a position nudge whose pulls cancel across the flock) — so clusters form tightly but never creep into a corner — while a thermal temperature jitters every heading so a cluster's centre wanders. The result: clusters that breathe and roam, loosening as they crowd and drifting as a whole.

A dense, tightly-packed cluster is a different story: the spring only pulls inward and the thermal kicks cancel across many boids, so it can sit almost still. The alignment nudge (the align / roam control — the classic third flocking rule, on by default at a gentle 0.05) fixes that by making neighbours match headings, so a whole cluster locks onto a shared direction and wanders as one. Turned up against the temperature, it's a genuine order/disorder switch: static clump below, marching flock above.

arm 1 · nearness 4.0 → 0.05 — fewer meetings, fewer bonds arm 2 · lifespan ×1.25 → ×0.4 — deaths rise arm 3 · breeding interval ×3^p — births slow cohesion = conservative spring · temp keeps clusters roaming align / roam · dense clusters pick a direction and wander (Vicsek)

World model · Heredity

Colour is the genome

A boid's genome is its hue and saturation, plus a beak gene and an eye gene. Children blend their parents' colours with mutation on top. A preferred colour family sweeps the tank in an endless cycle — bonding odds, predator diets and biased inheritance all pull the population toward it, and once ≥90% converge for 5 s, the wheel advances.

genome = hue° + saturation child = circular hue blend ± mutation 50% (bit-flip) beak gene — expressed by males, courtship bonus ×0.75–1.25 eye gene — both sexes, courtship bonus ×0.75–1.25 distant genomes court faster (shorter cooldown) diversity < 0.3 → inbreeding depression: disease fatality ×1–3, hazard ×1–1.5 immigration ships in fresh genomes — white birth ring, generation counter rule of thumb honoured: 50 / 500

World model · Development

A cell decides what to become

Turn on differentiate and the genome stops being decoration and starts being fate. Every cell begins grey and undecided; over a few seconds it commits to one of three lineages — a heart cell, a liver cell, a brain cell (red, green, blue) — and once it commits, it locks. The decision is irreversible, the way a real cell that has become muscle never wanders back to being anything else.

What triggers the choice is what triggers it in an embryo, minus the biochemistry — three forces pulling on an undecided cell at once. A morphogen gradient runs top to bottom, so a cell reads its own position and leans toward the fate of its band — Wolpert's French-flag rule, position as destiny. Its neighbours pull too: at positive coupling they reinforce one another (the community effect — cells agree, and clean organ territories crystallise); at negative coupling a committing cell pushes its neighbours the other way (lateral inhibition — the salt-and-pepper scatter of neurons among glia). And noise jitters the whole thing, so symmetry breaks where the gradient is ambiguous. Commitment builds faster once the neighbours have already decided — a wave of determination sweeping outward from the first cells to commit.

Then the tank's own heredity takes over. A committed pair's children inherit their parents' fate colour, so a newborn starts life biased toward the family lineage — but it is born grey and must still commit for itself, the way an embryo's daughter cells inherit a head start yet make their own call.

One caveat the physics forces on us: a boid always swims at full speed, so a flock never holds still — and a pattern you can't hold still, you can't see. Two controls tame it. Motility damps how far the cells drift; turn it down and they pack like tissue, the territories setting like stained glass. Settle ties that damping to the decision itself — undecided cells migrate, then freeze the moment they commit, so a lineage crystallises in place while its still-grey neighbours wander on, the way cells in an embryo roam until they know what they are and then stay put. This is a metaphor, not developmental biology — no genes regulating genes here — but the shapes it makes (positional bands, inhibition patterns, irreversible commitment) are the real ones.

three fates — heart · liver · brain (red / green / blue) undecided = grey; committed = vivid and locked (canalised) morphogen — vertical gradient, position sets fate (French flag) fate coupling +1 community (territories) ↔ −1 lateral inhibition (salt‑and‑pepper) commit rate — how long a cell hesitates before it locks motility 0 = pinned tissue · 1 = free-swimming (pattern smears) settle — undecided cells migrate, committed cells freeze in place children inherit the fate hue but are born grey — a biased head start

World model · Pathology

An epidemic needs contact

Disease spreads the same way love does: by collision. Repeated exposure infects; the infected wear a white dot and either die — much more often in an inbred tank — or recover immune for life. Bonded partners are the exception: infection trickles across the pair bond without touching.

infectious window 10 s (slider 5–60) base fatality 10% × inbreeding up to ×3 immunity lifelong R = mean infections per case, last 30 cases auto-disease mode seeds a case every 30–90 s (exports)

World model · Predation

The hunger clock

Predators are white boids with an appetite and the same physics. A meal buys ten minutes of peace — well, ten seconds — then hunger returns. Diet is programmable: hunting the wrong-family boids turns predators into an engine that accelerates the colour cycle.

sense 200 px · speed ×1.2 bump: chase nearest · lock: commit to one (white tail fin) diet any / favoured / other — “other” reinforces the cycle kill = beak-tip contact → splash

Part two

The render model

Render model · Layer stack

Ten layers, one WebGL frame

PixiJS draws the tank painter-style, bottom to top. Bodies are pooled, tinted sprites of a single teardrop texture; everything else is retessellated PIXI.Graphics. On low-power hardware the sprite batching is what buys the framerate.

Render model · Depth

A third dimension, rented cheaply

Depth is one extra coordinate, not a new engine. Each boid drifts through z on a slow random walk; the legacy 2D plane sits at mid-depth, so boids swim toward you past full size and shrink away behind it. Disease and personal space are the 3D collisions; bonding stays 2D — an on-screen encounter — and steering stays 2D too, so the ecosystem needs no retuning. Boids that overlap on screen gently push apart in z, so the draw order stays honest and the front/back flicker disappears.

z range 0–600 (slider, 0 = classic 2D) scale = 600 / (600 + z − DEPTH/2) z drift ≤ 35% of swim speed draw order far → near (continuous depth sort) overlapping boids layer apart in z — no flicker predators ignore z (v1)

Render model · Visual vocabulary

What you're seeing

Six recurring glyphs carry the story. Once you can read them, the tank narrates itself.

Tinted body — one teardrop texture, tinted per-boid at HSL L50; beak length and eye size are the genes made visible. Or swap in your own images — one pool per sex, picked at birth, sized by a scale slider.
Aura glow — the boid's own hue; a touch brighter for bonded pairs than for fertile adults still searching. The aura toggle sets it to gradient, flat, or off.
Bond line — a thin white thread between partners, a touch brighter while fertile or at a birth. One event fx switch cycles three states — all events, bond lines only, then none.
Birth ring — expanding pulse in the newborn's colour; white when the newcomer is an immigrant.
Death splash — rings and particles in the deceased's hue, scaled by its depth.
Motion trail — a tapering wake; the white dot on a body marks disease.

Render model · Cloth

Images that behave like cloth

Load your own pictures and they need not stay flat. A boid wearing an uploaded image can be drawn as a deforming mesh rather than a sprite: a slow wave travels through the whole picture, both axes at once, so it reads as cloth in water rather than a flag on a pole. Each boid gets its own phase, so a shoal never pulses in unison. Only upright images ripple — a body that rotates with its heading while the wave axis stays fixed reads wrong, so uprightness is the condition rather than a preference.

A second wave carries no geometry at all: a shadow rolling over the surface, shading the slope of the wave rather than its height, which is the difference between a curved surface and a gradient sliding across a photo. It only ever darkens — cloth in water is shaded on the far side of a swell, not lit above ambient — and on an LED panel that matters twice over, since brightening pixels is what makes a panel flicker. Three sliders: how far the cloth moves, how dark the shadow gets, and how many crests fit across the picture.

This is the one effect in the tank that is genuinely expensive. Every rippling boid needs its own mesh, and meshes cannot be batched the way sprites can — so where the flock costs one draw call for hundreds of bodies, this costs one each. It is built for a handful of image boids, not a crowd, and past a hard ceiling the surplus quietly stop rippling rather than let the tank stall.

wave runs on the GPU — the mesh itself never changes shadow follows the slope, not the height crests across the image 0.4–4 (the mesh sets the ceiling) tight ripples: more crests, less movement, more shadow one mesh — and one draw call — per rippling boid ripple 0 removes the meshes entirely, not just the motion

Render model · The panel

Upright, whichever way the panel hangs

The tank's real home is a 192×32 LED panel, and a panel can be hung either way up — portrait or landscape, turned in its own plane like a picture frame. Turn it, and everything drawn upright is suddenly upright only with respect to the canvas, not the room. A single angle fixes that: upright images counter-rotate by however far the panel has turned, so a face stays a face however the frame is mounted.

Nothing else moves. The tank keeps its own shape, the boids go on floating exactly as before, and a boid drawn at its heading needs no correction at all — it swims in the tank, and the tank turns with the panel. For now the angle is a slider; the intention is an inclinometer on the panel writing the same number.

Render model · Sonic vocabulary

What you're hearing

The tank can be listened to as well: press 🔊 on the dashboard, then tap the aquarium once (browsers insist on a gesture before sound may start). Nothing is a recording — every sound is synthesized live, and the score is played by the society itself. All pitches sit on a D minor scale, so the tank cannot play a wrong note. Close your eyes and it keeps narrating on many channels at once: the weight of the crowd, its colour and its size, courtships and marriages and divorces, epidemics, the arrival of a predator, generations coming and going — and now a melody sings over the top of it all. Fourteen voices, each a fader in the full-width mixer.

The bed — the state of the society.

drone body — population size drone brightness — crowding pressure warm fifth in the drone — fraction of boids bonded six coloured voices, one instrument each — the flock's colour balance (loudest colour = loudest voice) souring chord + quickening fever-pulse — the infected fraction (Dm curdling toward its tritone) radiant high shimmer, blooming — the population dwelling near your climax target a root tone gliding high↔sub — the boid-size slider (tiny = glassy, giant = deep) airy halo glowing in — the aura switched on voices opening from unison into a chord — the flock spreading apart (tight clump = one note, scattered = fanned open)

The melody — a line that sings over the texture.

a bright harpsichord-like arpeggio, phrasing and cadencing home — the generative lead (a Bach-style descending-fifths sequence in D minor whose figuration reshuffles each cycle, so it never quite repeats) a second voice answering a bar later, an octave up — the canon (the same line chasing itself, like a two-part invention; its own level and interval) the melody quickening or easing — the flock's speed, with an independent tempo knob to set its pace by hand

The events — moments in a life.

warm marimba note — a birth soft rising fifth — a new bond descending sigh — a bond broken (divorce · drifted apart · widowed) bass-drum thud — a death low two-note ostinato, quickening — a predator is hunting (faster = graver threat — the Jaws motif, E–F, in key) snare crack over the thud — a kill

Performance · The mixing desk

Composing with the tank

The two bars at the top of the dashboard turn the aquarium into an instrument you can play and record — a generative piece whose score is the society and whose performance is you moving the controls.

mixer — one vertical fader per voice; master leads and scales the whole mix preset scenes — pads that snap the entire dashboard (and the tank) to a saved settings file in one click; load a scene with 📂, right-click to clear, and they persist between visits record ⏺ — capture every slider & toggle move over time (preset presses included) as a replayable piece play / save / load — replay a recording in the tank, or keep it as a file to perform again later export 📦 — bake the recording into a self-contained page that loops the whole audiovisual piece forever, offline (a gallery/kiosk mode)

Because a preset press is recorded as the individual control changes it makes — not as a reference to the file — a recorded piece keeps working after the scene files are gone, and travels intact into the exported kiosk page. One caveat: switching universes (the ✦ Astro mode) is not captured, so compose a piece within a single world.

Context · Lineage

Where this sits

Composing this way has a history. You don't write the notes — you build a system whose behaviour is the music, then tend it. There is no single name for this exact instrument — a live artificial-life simulation driving synchronised generative graphics and synthesised sound, performed and recorded as parameter automation — but every layer of it belongs to a named tradition.

generative music — Brian Eno (~1995): build the system, not the piece; be a gardener, not an architect. A recording is just one snapshot of a system that could run forever — which is exactly what the 📦 export is. algorithmic composition — Iannis Xenakis: music grown from stochastic and physical processes. Driving sound from a simulation is squarely this lineage. sonification — mapping live state and events to sound (population→drone, infection→a souring chord, a birth→a note): parameter-mapping plus event cues. swarm / A-life music — Tim Blackwell (Swarm Music), Eduardo Reck Miranda: making music specifically from flocking and artificial life. "A society that sings" is a real practice, not just a metaphor. indeterminacy — John Cage: a fixed score, an ever-different performance. The recorder captures the gestures; the still-stochastic tank realises them fresh every time. live electronics / modular — playing a generative engine in real time by riding its parameters: the mixer faders and preset scenes are your performance surface.

In one line: a generative, sonified artificial-life instrument — generative music by way of sonification, in the swarm-music tradition, performed and captured as automation over an indeterminate engine. Terms to pull on if you want to go further: generative music · algorithmic composition · sonification · swarm music · process music · comprovisation · metacreation.