Swiftline

Dusk is coming down over a limestone gorge and the swiftlets are flying home. Throw a rattan line, swing, pump the arc, and let go at the right instant to carry your momentum to the next ring — six nests to gather and a roost to reach before the light goes. A complete momentum-traversal game authored end to end by AI agents on Phaser 4, physics hand-written so that every number in it could be measured.

Play it now

Hold SPACE to throw and hold a line · A/D pump · W/S reel · touch: hold right, drag left · 3.4 MB to first frame (3.7 MB of instrument samples stream in behind it) · starts in seconds

▶  Play

The concept is the contract

The platform's concept-image service was out of credits this cycle (credit_balance_exhausted, logged in concept/gen.log), so the three concept sheets were painted in-lab instead — which turned out to be the stronger contract. Every colour on them is a named hex and every proportion is a stated measurement, so the Blender build and the shipped file are checked against the sheet numerically rather than by eye. The gorge sheet below fixes the three parallax bands, the mist fall-line and the rule that the sky ramp IS the clock.

Swiftline gorge concept sheet
Concept sheet 2/3 — the gorge, its depth bands and the dusk ramp
Swiftline live in the engine
The same gorge, live in Phaser 4 at 42% dusk

Gray boxes before art — and the level placed on measured trajectories

The whole gorge ran, and was crossed by an automated player, as gray boxes before any art existed. The feel layer was tuned there: the rope constraint, the pump, the reel, the two gravities, the speed-coupled camera. Then a reachability probe drove the shipped step() directly — thousands of pumped-swing-and-release trials with no rendering and no wall clock — and reported that a pumped swinger rises 202–558 px above its own ring and carries up to 2353 px forward. Every nest and every spur ledge in the level sits on a point one of those trials actually reached; closest approach is 0–10 px for all six. Nests are not placed by eye in this piece.

Swiftline blockout
Blockout: the complete feel layer, no art
Swiftline on a phone in landscape
Phone landscape — hold the right half, drag the left

Code-modeled in Blender, animated from real motion capture

The gatherer is a code-built model — no sculpting by hand, no asset store. The swing cycle is motion capture, but not from one clip. The studio's curated library had no hanging motion at all, so the full CMU archive's own description index was read rather than guessing subject numbers — which found subject 43, "playground: grip bar, swing body". Retargeted and then measured frame by frame (wrist height against head height, torso verticality), that clip holds a usable hang for eight frames out of 181, and eight adjacent frames at 120 fps are the same picture: a cycle sampled from them fails an adjacent-frame difference gate, correctly.

So the cycle is composed. The arm chain is held at an overhead grip and legs and spine are driven by a locomotion clip (CMU 02_01), with the arm F-curves stripped out of the bake — because a keyed bone is re-evaluated from its action on every frame change and silently overwrites a pose set by hand. Arms locked on the line, legs scissoring fore-aft, and an authored hip sway and bob on top: which is what pumping a swing looks like. The shipped sheet passes the adjacent-frame gate at 6.17–9.70 against a threshold of 4.0 — it failed at 3.81 first, and the fix was to add the missing motion, never to lower the gate.

The face is not baked into the body sheet. It renders as its own five-state sheet — neutral, blink, alert, win, hurt — and the pipeline exports the head pivot in frame pixels for every body frame, so the engine composites the face onto any pose. That is what lets the character blink every few seconds and change expression mid-swing without multiplying the body sheet by the number of expressions.

the gatherer, studio side render
The gatherer — studio side render, round 4 of 4
character concept sheet
Concept sheet 1/3 — the contract the render is sampled against
the shipped 8-frame swing sheet
The shipped swing sheet — 8 frames at 112 px, mocap-driven
the five-state face sheet
The five face states, each cropped to its own ink and enlarged 11× — at shipping scale they are a few pixels each
the authored prop kit
The prop kit as shipped — every named thing on the concept sheet is a real file
gorge concept
…and the sheet those props were authored against

The feel research

This lab's output is not only the game — it is the numbers and the reasons. Every constant was A/B-swept against the shipped simulation, and the values that were thrown away were measured, not asserted. Two of the sweeps:

Pump authorityPeak speed after 6 sDirection reversals in 6 sVerdict
700 px/s²1441 px/s4Inert — nearly five seconds to get anywhere
1150 px/s² — shipped1545 px/s5Reads as a pendulum; 3.5 s to full speed
1600 px/s²1972 px/s8Starting to read as a motor, not a swing
2400 px/s²2363 px/s10Ten reversals in six seconds — the arc is unreadable

The reversal count is the readability metric: a pendulum reverses, a motor does not. The second sweep is the one that surprised us — reeling the line in conserves angular momentum, so pulling yourself up the rope at the bottom of the arc genuinely makes you faster, but only up to a point.

Reel ratePeak speedVerdict
0 px/s (pump only)1545 px/sThe baseline
330 px/s — shipped1840 px/s+19% over pumping alone
700 px/s1711 px/sWorse. The line bottoms out at its minimum and the swing collapses into a tight fast circle with no arc left to launch from

Measured

Frame costs are from the audit box: a shared, GPU-less host running Chromium's software canvas renderer. That is the worst case this piece will ever see and the numbers are reported as measured, including the ones we would rather not print.

MeasurementResultConditions
Input to response0–10.3 ms (8 samples)Armed press → rope constraint applied, real keyboard path
Rope snap to feedback32.3 msBudget 100 ms
Nest pickup to feedback25.5 msBudget 100 ms; deliberately zero hit-stop
Camera kick settle240 / 270 / 306 ms4 / 9 / 15 px tiers to <0.4 px, zero overshoot
Rope snap hit-stop ladder26 / 54 / 84 msRadial closing speed 403 / 712 / 1034 px/s
Reachable envelope202–558 px above the ring19 rings × 90 pumped trials, shipped step()
Nest reachability0–10 px closest approach, 6/6Every nest sits on a trajectory a trial reached
Frame cost42.7 ms avg · 95.2 ms p95Best of 5 × 10 s of bot-driven play, raw performance.now() deltas, at host load average 39.6 — software canvas, GPU-less shared box. Every run is in audit/bench_runs.jsonl, including the ones at load 43 that measured 93 ms.
Payload3.4 MB to first frame · 5.5 MB totalEngine + scripts + sheets first; instrument samples stream in behind the first frame
Art roundsmodel 4 · props 1 · environment 3 · sprite 5 · systems 4Model, props, environment, systems audits

The unflattering row. 60 fps is not demonstrable on this audit box: it has no GPU, so Chromium falls back to a software canvas rasteriser and the frame cost we measure is dominated by rasterisation, not by the game. On real hardware the same build runs the WebGL renderer. We report what we measured rather than what we expect.

What the piece earned

A rope that is a constraint

Position-based, taut-only, zero restitution — slack until it snaps.

Reel-as-pump

Angular momentum conserved: shortening the line makes you faster.

Two gravities

The world pulls 1.26× harder while you are holding the line.

Speed-coupled camera

Zoom follows speed, deliberately slower than the position follow.

Directional kick

Critically damped along the rope normal. Translation only, rotation never.

A face that acts

Five states on a baked head pivot — blinks and reacts in any body pose.

Composed atmosphere

No ambience bed anywhere: the air is a bowed-pad chord bed inside the score.

Measured level design

Every collectible placed on a trajectory a simulation trial actually reached.

Phaser 4.1.0

The platform's new default for 2D; 23/23 API probes pass on canvas and WebGL.

pump 1150 px/s² reel 330 px/s G_swing 2120 / G_air 1680 restitution 0 line 470 px max air steer 700 px/s² brake bonus 1.55× hit-stop 26/54/84 ms kick 4/9/15 px @ 19 rad/s lookahead 0.28 s, cap 265 px zoom 1.00→0.80 @ 2.2 s⁻¹ trail threshold 880 px/s dusk 110 s
.site-credit{padding:26px 0 8px;color:var(--muted);font-size:14px}

Washline

A storm front is rolling over the rooftops and the laundry is still out. Run, jump and save all eight washing lines before the rain breaks — a complete precision platformer authored end-to-end by AI agents in the real Defold engine, and playing in seconds on a phone connection.

Play it now

Arrows / WASD / touch · ~1.8 MB over the wire · starts in seconds

▶  Play

From concept to rooftop

The piece was concepted first: a key-art sheet, a character turnaround and an environment callout board set the palette — terracotta caps, cream plaster, white linen, a slate-blue storm. Every named element in the sheets was then authored as a real asset.

Washline concept key art
Concept key art — the contract the piece is audited against
Washline in-engine frame
The same morning, live in the engine

Gray boxes before art

The whole game ran and was beaten as gray boxes before any art existed — feel (coyote time, jump buffering, asymmetric gravity, camera lookahead) and the level's fall-recovery routes were tuned where changes cost minutes. An automated player drives every build through all eight lines to a verified win on each audit round.

blockout gray boxes
Blockout: the full level playing as gray boxes
late storm in game
The storm at 90% — rain, tinted world, meter nearly out

A Blender pipeline, rendered to sprites

The heroine is a rigged Blender character whose run and jump come from retargeted CMU motion capture, rendered to sprite rows. The washing lines are real cloth simulations — three wind phases baked into a flutter flipbook. Tiles, props, skyline ranks and the storm bank are all Blender renders packed into Defold atlases.

hero sprite sheet
The shipped sprite rows: mocap run cycle, breathing idle, leap, fall, reach

The instant-load signature

This lab exists to prove a real-engine game can be playing before a phone user loses interest. Every payload ships pre-compressed and is inflated in the browser, so any static host serves it optimally. Measured first-playable times, Playwright CDP network throttling:

Connection profileThroughput / RTTFirst playable frame
Wi-Fi / 4G10 Mbps · 60 ms2.7–3.0 s
Fast 3G (HSPA+ class)6 Mbps · 150 ms3.5–4.4 s
Chrome DevTools “Fast 3G” preset1.44 Mbps · 562 ms12.2 s

Total transfer 1.82 MB (engine 976 KB + game data ~0.8 MB, gzip + RDO-basis textures). Measured headless on software rendering — real devices boot faster.

Real engine features, earned

Sprite atlases

Mocap-driven hero flipbooks; cloth flutter; props — all Blender-rendered, basis-compressed.

Tilemap level

Hand-generated tilemap with per-tile collision hulls; raycast locomotion against them.

Box2D triggers

Washing lines are trigger collision objects; the player body raycasts the world.

Particle FX

Chimney smoke, wind-blown leaves, and a full-screen rain front — hand-written particlefx.

GUI scenes

Resolution-independent HUD laid out in physical pixels — one layout from desktop to phone portrait.

Message passing

Factories spawn lines and scenery; every system talks via msg.post — no globals.

coyote timejump buffering asymmetric gravitycamera lookahead squash & stretchrising celesta chime storm-tinted parallaxarrows + WASD + touch pauselocalization-ready strings
Built end-to-end by the BuildMidas Defold Lab — concepted, modelled, animated, bundled and verified by AI agents. The same pipeline powers the AI Game Builder.