BLOBBO/lanes/LANE-H-ghost-title.md
type-two fedb43817c Lane docs F (audio), G (colour zones/puddles/MEGA-MINI), H (ghost/title)
Driven by the live fresh-eyes finding: a naive racer finishes with 0% paint —
the core mechanic is currently skippable. G makes paint route-guaranteed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 11:31:41 +10:00

2.7 KiB

Lane H — Ghost replay + title screen

Owns: src/ghost/, src/ui/, demos/lane-h.html, src/demo/lane-h.ts. Never touches: contracts, world, game, main, package.json, other lanes' dirs. No new deps.

Mission

Two pieces that turn a tech slice into a GAME you return to: a ghost of your best run to race against, and a title card that explains the game in five seconds (and unlocks audio).

Deliverables

  1. src/ghost/recorder.tsGhostRecorder: on race:started, record the blob root's position + uniform scale at 15Hz into a flat Float32Array-backed buffer (cap ~5 min). On race:finished, if this run is the new best, save quantized (int16 centimeters is plenty) + the time to localStorage blobbo:ghost (base64). Keep total under ~200KB.
  2. src/ghost/player.tsGhostPlayer: if a saved ghost exists, on race:started spawn a translucent ghost blob (simple sphere + eyes is fine, opacity ~0.35, no physics — kinematic visual only) and replay it in race time with linear interpolation between samples. Despawn on finish/respawn. The ghost must be OBVIOUSLY not-you (ghostly white/desaturated, slight bob).
  3. src/ghost/install.tsinstallGhost(world, blob) wiring both to events.
  4. src/ui/title.tsinstallTitle(world): full-screen overlay on boot:
    • big BLOBBO wordmark (styled CSS bubble text is fine — thick white letters, rainbow paint-drip accents, Comic-adjacent but tasteful),
    • one-line pitch: "Race. Get painted. Paint is power.",
    • controls card: WASD/stick · Space/A jump · R/Start restart,
    • a fat PLAY button. On click/keypress/gamepad-button: fade out, emit ui:play on world.events (audio unlocks on this), start allowed.
    • While Rapier/world is still booting, show the same overlay with a wobbling "loading…" blob dot instead of PLAY (installTitle can be handed a promise).
    • Show saved best time + "👻 ghost ready" if blobbo:ghost exists.
  5. Demo demos/lane-h.html + src/demo/lane-h.ts: fake a 20s scripted "run" (a ball on a circle), record it, finish, then restart and race the ghost. Title screen in front. Debug key G wipes the saved ghost.

Acceptance

  • npm run build passes; demo shows title → play → run 1 records → run 2 shows interpolated ghost racing the circle; localStorage survives reload; wipe works.
  • ui:play emitted exactly once per page life; overlay never reappears mid-game.
  • Ghost replay drift vs recorded path < one blob radius at all sample points (it's the SAME deterministic path in the demo — verify numerically).
  • No edits outside owned paths.

Events

Consume race:started, race:finished {time,best}. Emit ui:play only.