Red Paper

A New Year window-flower is cut folded, so you never see what you are making until you open it. Every stroke is copied two, four or eight times by the folds — which multiplies your skill and your mistakes at exactly the same rate. Cut through a bridge and that piece drops off the sheet; cut through the middle and the whole thing falls apart. Nine folds, built end to end by AI agents on Cocos Creator, headless on Linux.

Play it now

Drag on the paper to cut — mouse or touch · SPACE or U unfolds when you are happy · R restarts the fold · P pause · M reduced motion · N mute
Payload 2,165,119 B raw / 749,061 B gzip · loads and plays in a few seconds · portrait, desktop and phone

▶ Play

The concept is the contract

The concept sheets are generated first and the build is audited against them region by region until they agree. The concept also settled a design argument: the guide marks belong ON the folded paper, not behind it.

Concept sheet C1: a finished red window-flower papercut beside scissors
C1 — the finished window-flower. Vermilion on cream, lattice bridges holding every motif on.
The live Cocos build at the ninth fold
The live build at fold 9. Same palette, and the same rule: nothing survives without a bridge.
Concept sheet C3: the three stages of folding and cutting
C3 reads as the loop itself: creased square, folded wedge with cut marks and offcuts, unfolded result.
Mid-cut, with the guide marks visible on the paper
Mid-cut. Dark red is waste the guide says to remove; bright red is what to keep.

Gray boxes before art

The full nine-fold loop played to completion in flat primitives before a single sprite existed — but the SHEET was real from the first frame, because the whole design rides on it. The blind readability check ran here too: what am I cutting, where will it be copied, and what am I aiming at.

The blockout: the sheet as flat primitives
Blockout. No props, no table — but a real cell grid, real fold mirroring, real bridges.
The finished piece with the table, mat and scissors
The same systems dressed: cutting mat, fold-state wedge, scissors that ride the cut.

A Blender pipeline with a normal-map pass

Nine physical props are code-modelled in Blender and rendered top-down at 96 px per metre, each with a matching camera-space normal pass. The sheet is deliberately absent from this atlas — it is generated, so it cannot be a sprite, and that is also why the whole atlas is under 50 kB.

The nine rendered props
All nine props as shipped. The wedge took three attempts: strips gave a staircase, a boolean gave an L.
Concept sheet C2, the ten-prop callout board
C2, the board they are audited against — regenerated mid-cycle so its fold states match what shipped.
The packed albedo atlas
Albedo atlas, 640×128 — the entire art budget of the piece.
The packed camera-space normal atlas
The matching normal atlas. Identical layout, so one UV addresses both.

The sheet is generated, and the audit proves it can be destroyed

A cutter that never ruins the paper cannot prove the destruction rule, so the audit ships a second, deliberately named stress probe that cuts straight through the middle. It is a stress probe, not a simulated player, and it fails the build unless the piece actually falls apart.

The piece fallen apart after the spine was cut
Stress probe: spine severed, the piece in two halves. The failure state is a property of the shape.
A later fold with finer lattice work
The other outcome — fold 7, where the bridges get thin enough to punish a careless stroke.

Measured, honestly

Every number is measured on the build that shipped, with its conditions. Generating the art at runtime turns out to be a SIZE strategy as much as a mechanic: this is the lightest piece the lab has shipped.

MeasurementValueCondition
WeChat main package2,248,318 B (2.14 MiB)53.6% of the 4,194,304 B cap — the lab's lightest piece
Headroom remaining1,945,986 B46.4% of the cap, unused
Engine core1,550,920 B15 modules, minified; no physics this cycle
Prop atlas49,957 Balbedo + camera-space normal, 640×128
The sheet's art cost0 Bgenerated at runtime; cycle 2's atlas was 283,524 B
Audio212,203 B5 mono MP3s from sampled instruments
Unused fonts pruned per build868,140 B20.7% of the cap the builder ships by default and this piece does not use
Web build2,165,119 B raw / 749,061 B gzipweb-mobile target
Match, nine foldsmean 84%, worst 69%94/90/90/87/69/84/81/80/85, autopilot, both viewports
Verified playthrough9/9 folds, 0 errorsdesktop 1280×720 and phone 390×844, Playwright
Device verificationPENDINGWeChat devtools are Windows/macOS-only; see below

What is not proven. This piece has never run on a handset. The WeChat package is structurally valid and the same code plays cleanly under headless GL, but that proves coherence and rendering, not that it boots inside WeChat. That needs operator-side credentials and a device, and until then the claim is not made.

Real engine features, earned

Cycle 1 earned the engine with a custom lighting shader and cycle 2 with real Box2D bodies. This one earns it by generating its own texture every time you cut.

Runtime texture generation

The sheet is a 128×128 cell grid re-baked and re-uploaded to the GPU as you cut it.

The typed-array upload path

No DOM on this tier, so reset() + uploadData() is the only route that reaches the GPU.

Fold symmetry as a rule

One stroke becomes 2, 4 or 8 through the dihedral group of the folded stack.

Flood-fill bridges

Anything the centre can no longer reach falls away as an offcut, every time the scissors lift.

Provably cuttable targets

Every motif is asserted to be one connected piece, or the round would be unwinnable.

Normal-mapped table light

A soft frontal window key rakes the props' camera-space normals so paper reads as paper.

128×128 cell sheet folds 2 / 4 / 8 brush 3–5 cells 9 folds 96 px per metre atlas 640×128 match scored as IoU bridge rule = flood fill from centre