creatures/ -- the 2D creature factory
A small, reusable factory for procedural side-view animals, decomposed by concern (factories +
a composer, not one huge file). It is consumed by the First Light gallery piece
(../creatures.html) today and is meant to be included by the Natura world renderer next, so a
world can draw its agents as articulated models instead of dots.
Layers (each its own file, one concern)
species.js DATA what animals exist -- proportion/colour tables (SPECIES quadrupeds, BIRDS bipeds).
Adding a creature = adding a row here. No drawing, no behaviour.
render.js DRAWING how a def is drawn -- drawCreature (quadruped) + drawBird (biped), with the
level-of-detail resolve (far silhouette -> full model). Math helpers internal.
behaviour.js DECISION what an animal does over time -- BEH loops of {posture, movement, gait} segments,
GALLOP, and targetOf() to pick the current segment. Never touches the canvas.
voice.js SOUND a reusable WebAudio VOICE per creature -- CreatureVoice.play(ctx,dest,name,t,opts).
Band-limited transient/textural only (no square/saw, no sustained drone); variants
for variety; SCENES (marshNight, dayGarden). Context-agnostic (a live AudioContext
AND an OfflineAudioContext), so voice-check.html VERIFIES it device-free.
creatures.js COMPOSER the facade -- wires the three together into one surface (draw / SPEC / isBird /
BEH / GALLOP / targetOf / mulberry / clamp). The only thing a consumer needs.
(voice.js self-attaches Creatures.voice when present; load it too if you want sound.)
The audio bench: voice-check.html. Renders any voice/scene through an OfflineAudioContext (no
speakers, no desktop) and draws its FFT spectrogram + metrics -- the device-free, decisive check.
?voice=NAME / ?scene=NAME / ?variant=NAME. Use it before trusting a sound; it caught (and led to
fixes for) the duck under-level, the cricket high-freq skirt, and the grain-onset click.
Data flows one way: species (data) -> render (draws it), and behaviour (decides) -> a pose -> render (draws that pose). Render depends on nothing; the composer depends on all three.
Contracts
Creatures.draw(ctx, name, x, y, dir, phase, scale, pose)-- resolvename, dispatch to the right body plan.diris +1/-1 facing;phaseis the gait cycle [0,1);pose(optional) is the eased posture{neck, ear, stand, peck, gait, lod}.Creatures.targetOf(c, e)-- for a creaturecwith{beh, seed}at loop timee(seconds), the active behaviour segment. The consumer eases its live pose toward it (so heads raise and legs plant smoothly) -- easing is scene policy, not library policy.- Determinism: all texture/scatter randomness comes from
mulberry(seed)(no Date/Math.random), so a frame is reproducible.
Add a creature
- Add a row to
SPECIES(quadruped) orBIRDS(bird) inspecies.js. - If it needs a new feature (a horn, a sheen, stockings), add a flag there and a small gated block
in
render.js. Most creatures need no render change. node creatures/creatures.test.js(data + wiring), then eyeball?montage=<name>/?zoom=<name>on../creatures.html.
Consume it
Load the four scripts in order (they attach to window), then use the facade:
<script src="creatures/species.js"></script>
<script src="creatures/render.js"></script>
<script src="creatures/behaviour.js"></script>
<script src="creatures/creatures.js"></script>
<!-- then: Creatures.draw(ctx, 'deer', x, y, 1, phase, scale, pose) -->
Node: require('./creatures/creatures') (UMD) -- used by the test.
Deploy note
The gallery piece ships as art/first-light.html plus art/creatures/*.js (the four runtime
modules, copied from here). The test and this doc stay here in the source and are not shipped.