clone

an endless marble-race generator in the browser; the url is the seed, so every track can be shared

main
marbles / docs / stall-fixes-2026-09-30.md
stall-fixes-2026-09-30.md 3.2K source

Track stall fixes — September 30, 2026

Continues the unfinished diagnostic work in the August recovery sample.

Causes and changes

Independent braid lanes were joined by collision geometry. A segment can contain two independent alternate paths. Their curves were concatenated, then extruded as one ribbon. The triangles connecting the end of one lane to the start of the other created invisible floors and walls across otherwise empty space. In rail-sample-015 segment 14, that wall blocked the alternate icy lane and caused congestion on the main line. The shared proxy builder now breaks ribbons at discontinuous authored endpoints. Independent strips are packed into one mesh with separate vertex/triangle sets, keeping the native mesh-handle budget bounded without connecting the strips.

An older rotated checkpoint blocked a later ramp. In rail-sample-008, segment 9's geometry folds into segment 11 after gravity reorientation. Removing only segment 9 from the six-chunk repro made the ramp/helix run clear. Changing traction would not fix this obstruction. Static collision categories now identify stream checkpoints; each live racer contacts its own checkpoint and its two connected neighbors. Racers still collide with one another, and respawn ghost filters preserve the checkpoint mask. This prevents unrelated folded checkpoints from blocking the active channel while preserving connected transitions.

This changes collision behavior, not seeded layouts. Existing generation goldens and generator version remain unchanged. World-space visual overlaps and broad camera occlusion remain separate generation/presentation concerns.

Verification

  • All 222 Deno tests passed, including measured collision fidelity, generation goldens, jump/reorientation/spur physics, multi-marble contacts and determinism.
  • New regressions assert disconnected collision topology, connected-window continuity, native ghost/respawn mask behavior, and both recorded layouts clearing with real Box3D physics and no respawn or escape-hop fallback.
  • Browser stress test: isolated Chrome runs, 401 racers, 300 deterministic simulated seconds per seed, real streaming client, diagnostics enabled.
Seed Hero reached Fall/stall recovery events Recorded problem tiles
rail-sample-008 Segment 17, about 1135 units 0 Ramp/helix cleared
rail-sample-015 Segment 19, about 1166 units 2 Icy braid cleared

Neither hero died; neither browser run produced a page/console error. Both remaining recovery events were at end-hole-rounded drop cups, outside the recorded braid cluster. Drop-cup congestion/recovery remains a follow-up target; this result does not claim every possible generated track is stall-free.

The native shim must be rebuilt with deno task build:physics when distributing these changes. This task requires Emscripten and CMake; deno task build bundles the browser code separately. The local native module was rebuilt and used for all verification above.