Phaser Lab piece 01 · verified playthrough, desktop + mobile

Cinder Courier

Night has taken the mountain shrine and every brazier is cold. A small fox courier carries the last ember up the ledges — relight all three before the path runs out, stomping ash-sprites and cinder crates on the way. A complete precision platformer authored end-to-end by AI agents in Phaser 3, built feel-first: every movement constant was tuned and measured on gray boxes before a single sprite existed.

Play it now

Arrows / A·D + Space, hold to jump higher · touch pads on phones · ~3.2 MB · M sound · P pause

▶  Play

Concept as contract

The piece was concepted first — a fox courier with an ember lantern, an ash-sprite enemy, a props sheet and a twilight-shrine mood board set the palette: russet against indigo night, ember orange as the only warm light. Every named element in those sheets was then authored as a real asset, and every audit round compared the build against them.

Cinder Courier fox concept
The hero concept — the contract the fox is audited against
Cinder Courier finale in-engine
"The shrine glows again" — the win state, live in the engine at the shrine gate

Feel first, art later

The whole game ran and was beaten as gray boxes before any art existed. The movement layer is the lab's product: asymmetric gravity with an apex hang, coyote time, jump buffering, a facing-lookahead camera with a grounded vertical anchor — each constant recorded in FEEL_NOTES.md with the reason it holds its value and what the rejected values measured. An automated player beats every build end to end on each audit round.

gray-box blockout
The blockout: full level playing as gray boxes, feel complete
From FEEL_NOTES.md — the lab's research output
G_FALL 3800 = 1.8 × G_RISE. Measured rise 345 ms vs fall 299 ms over the same 122 px: the rise carries intent, the fall carries weight. Rejected symmetric 2100/2100 — measured rise:fall ≈ 1.0, airtime +35%, "the fox hung like a balloon."
COYOTE 90 ms + one frame: the ledge exit happens BETWEEN frames — an uncompensated window silently shrinks by a frame and the feature dies at low fps. Found by measurement, not by eye.
Hit-stop 40/70/110 ms by impact class — scaled to how much the event matters and how often it fires. Rejected uniform 80 ms: classes became indistinguishable and frequent crate breaks dragged the tempo.

A Blender pipeline, rendered to sprites

The fox is a voxel-fused Blender build — audited over five rounds against its concept with render-sampled palette checks — rigged and driven by retargeted CMU motion capture (run clip 09_02, jump 16_01 with poses picked by measured hip velocity), rendered to sprite rows. The ash-sprite, braziers, crates, embers, shrine gate, tiles and all three parallax mountain layers are kit-built Blender renders. Audio is the platform's sampled-instrument engine: a celesta pitch ladder for ember streaks, harp-and-horn swells for braziers, footstep and impact families for the body, procedural night wind underneath.

shipped sprite rows: fox run, jump, idle; ash-sprite hover and pop
The shipped rows: mocap run cycle · jump rise/apex/fall + breathing idle · ash-sprite hover and stomp-pop

The measured feel

The blockout ships its own benchmark harness (Playwright, canvas renderer, raw performance.now() frame deltas — this lab's audit host has no GPU, and headless frame throttling plus engine delta smoothing otherwise fake a clean 60). Numbers below are from quiet-load windows on that shared host; sim-space distances are load-robust.

MetricMeasuredConditions
Input → jump velocity11–32 ms (≤2 frames)DOM keydown timestamp → velocity applied
Coyote windowhonored at 50 ms · refused at 160 msscripted ledge walk-off, 90 ms + 1 frame window
Jump bufferfires 43 ms after landing-frame presspressed 90 ms before touchdown
Run-up / stop95% max speed in 135 ms · stop in 17 pxfull-hold from standstill / release at max
Jump arcfull 122 px in 345 ms up, 299 ms down · tap 39 pxhold vs 70 ms tap; 48 px tiles
Event feedback≤42 ms, every interactive eventbudget 100 ms; same-tick visual response
Automated playthrough3/3 braziers, win in 18 s, zero errorsreactive input bot, desktop; repeated as confirming audit
Frame cost (this audit host)best 21.1 ms avg · 32.7 ms p95software canvas, no GPU, shared box under residual load — real hardware runs the WebGL renderer at 60
Payload3.2 MB · 66 filesengine 1.2 MB + art 0.7 MB + sampled audio 1.2 MB

Real engine features, earned

Arcade physics, state-driven

World gravity zero; the body's gravity is chosen per frame — rise, apex hang, fall — with a terminal clamp.

Manual camera rig

Exponential smoothing, facing lookahead re-aimed slower than position, grounded vertical anchor with asymmetric windows, decaying translation-only shake.

RenderTexture tilemaps

Each platform's tile grid baked once into a RenderTexture — one draw per platform per frame on the software-canvas floor.

Sprite animation

Mocap frame rows; run rate tied to ground speed; jump pose picked by vertical velocity; interrupt-safe squash tweens.

Particles everywhere

Run-skid dust, crate shards under gravity, ash pops, ember sparkles, per-brazier flame loops — five tuned emitters.

Sampled-instrument audio

The platform Web Audio engine: enveloped sampled voices, variation jitter, FX sends, first-gesture unlock, procedural wind ambience.

coyote 90 ms + 1 framebuffer 130 ms fall gravity 1.8×apex hang |vy|<55 jump-cut 0.42hit-stop 40/70/110 ms shake decay 11/s, no rotationlookahead 96 px squash 1.28/0.72 @ 70 mstwo-tier stomp bounce celesta ember ladderreduced-motion 0.2× arrows + WASD + touchlocalization-ready strings