BLOBBO/lanes/LANE-C-machine.md
type-two 969f602dd4 Foundation: vite+ts+three+rapier scaffold, frozen contracts, lane docs A-E
Fixed-step world runtime, event bus wire protocol between lanes, integration
seam (game.ts) with placeholder ball. Lanes A/B/C own disjoint dirs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 19:55:43 +10:00

3.0 KiB

Lane C — Machine (Rube Goldberg toolkit)

Owns: src/machine/, demos/lane-c.html, src/demo/lane-c.ts. Never touches: src/contracts.ts, src/world.ts, src/game.ts, src/main.ts, package.json, other lanes' dirs. No new deps — three + rapier only.

Mission

Player-triggered contraptions with mandatory telegraphs (GDD §5.4). Contraptions are data-placeable parts that chain via signals — the course is a machine.

Deliverables (src/machine/)

  1. telegraph.ts — helper: given a mesh + duration (default 0.5s), play an unmissable windup (flash + shake/scale pulse + optional emissive) then resolve. EVERY contraption that applies force or dumps paint MUST telegraph first. This is a design pillar, not decoration.
  2. parts.ts — each part takes a config {id, position, ..., onSignal?, emits?}, registers physics + visuals, listens/emits on world.events:
    • PressurePlate {massThreshold} — depresses under weight; uses blob effective mass (body.mass()); emits its emits signal on trip.
    • SeeSaw — plank on Rapier revolute joint; purely physical (heavy blob dominates it).
    • SpringBoot {impulse, direction} — on signal: telegraph → kick anything in its strike volume.
    • BucketDump {color, radius} — on signal: telegraph (teeter!) → tips; emits paint:request-splat {point, color, radius} for everything under it (paint lane renders the splat; you also spawn a brief visual slosh mesh).
    • ConveyorBelt {velocity} — surface that adds velocity to bodies on it.
    • BubbleArch {fraction} — sensor volume; on blob overlap emits paint:request-cleanse {fraction} + bubble particle burst.
    • Fan {force, direction} — constant force volume (pushes light blobs hard, heavy blobs barely — mass does the work).
  3. surfaces.tsSurfaceMaterial registry per contracts (normal, ice, oil, honey, mud, water): friction/restitution + tags; helper applySurface(collider, name) + a way for the blob controller to query the surface under a body (surfaceAt(point)).
  4. Chain demo demos/lane-c.html + src/demo/lane-c.ts: heavy test ball (your own stub — do NOT import Lane A) rolls onto PressurePlate → SpringBoot → ball lands on SeeSaw → tips into BucketDump trigger → bucket teeters and dumps (log the paint event), plus a ConveyorBelt and a BubbleArch on the side, and an ice + honey patch to feel surfaces. Debug key T re-runs the ball.

Acceptance

  • npm run build passes; the full chain runs end-to-end on one ball with a visible telegraph before every kick/dump.
  • PressurePlate does NOT trip below its mass threshold (test with a light ball).
  • Surfaces measurably change rolling behavior.
  • No edits outside owned paths.

Contracts (frozen — read src/contracts.ts first)

Emit: machine:signal {id}, paint:request-splat, paint:request-cleanse. Nothing in this lane imports from src/paint/ or src/blob/ — events only.