190a6e27d3
4 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
190a6e27d3 |
feat(paint): METEOR blend + yellow ZAP — the palette is complete
Three GDD §6 features land together, plus the design bug their verification
exposed.
METEOR (red+orange both >=20%): "smash light barriers" made literal. New
createSmashWall part — a brick-seamed light barrier, solid to everyone, but a
METEOR blob that RAMS it (>=5 u/s) shatters it into 8 real dynamic brick
shards that carry your momentum; rebuilds on race:respawn. Spec kind
'smashwall' with needColors for data courses. HUD shows "☄ METEOR" replacing
the pair's BURN/BOUNCE rows (GDD: the blend replaces its pair) and the ember
trail burns 2.2x while blended.
ZAP (yellow >=20%): "trigger colour-keyed machinery at range". New
machine/zap.ts — a charged blob pulses every 3s and fires any declared zap
target's machine:signal within radius, with an expanding arc ring. Breakfast
declares the fork's spring boot: purple earns it by WEIGHT on the plate,
yellow HOTWIRES it — verified the full arc: pulse -> boot telegraph -> kick
vy 10.6 -> lands on the finish podium. Yellow bubbles by the fork are the
source. Spec courses declare `zapTargets`. HUD shows "⚡ ZAP".
THE BUG THE WALL EXPOSED: the finale gate sat at z-59, but the finish box
reaches z-57.2 (podium-face bonks must count) and the podium collider face is
at z-58 — so in a LIVE race you finished before ever touching the gate; it
only ever blocked test blobs with the race idle. The whole gauntlet now lives
at z-56, in FRONT of the line: centre = green gate, left = METEOR smash wall,
right gap plugged (the MINI tunnel roof already gates x3..10), far left = open
detour. The cleanse arch moves to x-6.5/z-54.5 — at x-4.5 its zone overlapped
the METEOR approach and stripped the blend one step before the wall.
Verified in-browser (atomic calls; the wall-clock coverage cache and the
background sim poisoned split observations): clean blob bonks with race
running; METEOR blob shatters (8 shards, signal, drives through rubble to
"you finished 29% ORANGE"); wall rebuilds on R; zap fires exactly once per
cooldown. hasMeteor/hasZap are pure + unit-tested (58 assertions, 10 suites).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
2777a580c9 |
feat(paint): ORANGE = BOUNCE — plug in the buff that was wired but dead
`jumpMul` has been plumbed end-to-end since Lane A — the controller multiplies take-off speed by it, BuffSystem copies it every step — but computeModifiers hardcoded `jumpMul: 1`, so a finished mechanic sat unplugged and 2 of the 7 palette colours (orange, yellow) had neither an effect nor a single source in any course. Orange now drives it: jumpMul 1.0 -> 1.5 at full strength (BOUNCE_JUMP, GDD §6 "rubberized"), same buffStrength curve as every other buff. Paint source: orange bubbles on Breakfast Rush's high shelf, right before the gap-jump lip — the one place in the game where jump height IS the problem, so the buff has an obvious purpose instead of being decoration. Deliberately opt-in and deliberately costly: they sit inside the GREEN grip zone, so grabbing orange dilutes your green. Route for the jump or route for the grip. Tuned during verification: the field uses impulse 1, not the default 3 — at full strength the pops stacked and launched the blob 3.3u above the shelf right at the lip, throwing off a jump this course is finely tuned around. Verified end-to-end: orange 61% -> jumpMul 1.424 (matches buffStrength exactly), take-off 7.10 -> 10.30, jump height 1.95 -> 3.87 (nearly double); HUD reads "BOUNCE ×1.41" in orange; rolling the shelf pops 4 bubbles per pass. New test assertions cover the 19%/45%/70% curve AND pin it to BOUNCE_JUMP, so a regression to a constant 1 fails loudly instead of silently removing the buff (53 assertions, 10 suites green). Palette now 6/7 usable. Yellow ZAP is the remaining gap and is real design work (triggering machinery at range), not a one-liner. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
3699a1635a |
Lane G: colour zones, paint puddles, MEGA/MINI scale buffs
Fixes the live finding that a racer can finish with 0% paint. Paint is now ROUTE-guaranteed by ground puddles, and colours come in single-colour zones so buffs actually cross the 20% threshold. - paint/puddles.ts: PaintPuddle + installPuddles. Flat coloured strips (no collider) that stamp the blob's underside via skin.splatAtPoint on a ~6/s cadence while rolling through, emitting paint:splatted. The body doesn't physically tumble (rotations locked), so an accumulated roll phase walks the contact point along the travel great circle — a straight run paints a stripe and coverage climbs instead of piling on the south pole. - paint/coverage-math.ts: extend computeModifiers with purple MEGA (size→1.45 + heavier) and pink MINI (size→0.62 + lighter than clean at high %). They fight: net size uses (purple − pink) strength; mass floored so MINI stays positive. (Lives here, not buffs.ts, because the pure mapping must stay THREE-free for the bare-node test; BuffSystem already forwards mods.size/massMul unchanged.) - paint/coverage-math.test.ts: +MEGA/MINI/fight cases (48 assertions pass). - course/zones.ts: installZones lays RED/GREEN/BLUE puddles down the centre line and the PURPLE(left)/PINK(right) fork onto the machine district — a pressure plate (baseMass*1.25) + boot on the MEGA lane, a visibly-low pink tunnel (underside y≈1.12) on the MINI lane. Returns cannon configs for integration. - demo (demos/lane-g.html + src/demo/lane-g.ts): drive the zones, F = hands-free hold-forward, 1-4 teleport to each zone, live coverage/size/mass + plate HUD. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
eed2eb2646 |
Lane B (Paint): splat pipeline, coverage compute, buff/threshold framework
The core invention: paint lands on the blob body where projectiles hit, live
per-colour coverage % is computed from a quantized UV mask, and coverage drives
buffs per GDD §6 MVP subset (RED speed+embers, GREEN grip, BLUE waterproof,
total→mass, 20% activate / 70% super+glow).
- src/paint/skin.ts PaintSkin: Canvas-2D mask on mesh UVs → CanvasTexture;
splatAtPoint raycasts impact→face UV; dual soft-canvas
+ hard quantized-index mask so coverage is exact
integer bucketing (never getImageData); 250ms cache;
scrub-hole cleanse; U-seam wrap.
- src/paint/coverage-math.ts pure, unit-tested: countBuckets, coverage report,
buffStrength, computeModifiers.
- src/paint/cannon.ts PaintCannon: gravity-arc glob projectiles (manual
swept sphere test), target-leading ballistic solve,
fires on interval AND machine:signal; emits paint:splatted.
- src/paint/buffs.ts BuffSystem: coverage→modifiers each step + ember trail
(additive Points) + super-state emissive pulse.
- src/paint/hud.ts PaintHUD: per-colour bars + active buff kit (throttled).
- src/paint/index.ts exports + installPaint() wiring the inbound Lane C
protocol (request-splat proximity-gated / request-cleanse).
- src/demo/lane-b.ts stub ball orbiting a RED and GREEN cannon; HUD live;
debug keys for fire/signal/flood/cleanse/pause.
- src/paint/coverage-math.test.ts 32 assertions (node --experimental-strip-types).
build: tsc strict + vite pass. No edits outside owned paths; contracts frozen.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|