Wire the platformer's rendering/input (glemy/game_platformer), verified via a new browser-check using captured-GPU-uniform position checks
Context
RM-034 Phase 2: wiring the platformer's already-verified pure logic (decision 0059) to real rendering and input, mirroring glemy/game_breakout's own Phase 2 (decision 0053) structurally. Only the player is a real physics.Entity, rendered via the existing WebGPU pipeline unchanged; platforms and the goal are CSS-div overlays, same category of technique as Breakout's paddle/bricks. Genuinely simpler than Breakout's own equivalent phase in one real way: platforms and the goal are static and never destroyed (unlike Breakout's destructible bricks), so there is no Brick.id/event-driven-hide problem to solve at all -- every overlay element is created once at startup and never touched again. This phase also needed its own real-browser verification script, and since the player renders through WebGPU (not a CSS div, unlike Breakout's paddle), confirming real keyboard-driven movement needed a different technique than browser_check_breakout.ts's own DOM-position reads.
Options considered
Decision
Built glemy/game_platformer.gleam (tick_and_render/start/loop/main, no score-equivalent needed since this game has none) and glemy/game_platformer_ffi.mjs (setStatusMessage/createLevelElements -- platforms and goal created once, no hide/destroy counterpart needed -- playJumpSound/playLandSound, its own AudioContext instance) plus platformer.html. Extended tools/browser_check_shared.ts's bootstrap to a third caller (already extracted for exactly this at Breakout's own Phase 2, decision 0053 -- now confirmed correctly scoped by a real third use, not over-engineered for two). Added tools/browser_check_platformer.ts, reusing the exact captured-GPU-uniform-buffer technique tools/browser_check.ts already established for Tiers' click-to-spawn confirmation (adapted here to confirm real ArrowRight movement and a real space-triggered jump moved the player in world space), plus a deterministic real fall-death check (hold one direction key from spawn, no jump, reaching a real "You fell!" status within ~2s).
Verification
gleam test and gleam test --target javascript both pass -- 281 Erlang / 308 JavaScript, exactly the prior baseline (281/306 as of decision 0059) plus 2 new @target(javascript)-only tick_and_render integration tests using a real OffscreenCanvas (decision 0015's pattern). deno task check-warnings passes after updating the baseline (104 warnings, every new entry confirmed as the already-documented @target(javascript) target-gating artifact under the new game_platformer.gleam/game_platformer_test.gleam files -- including an 'Empty module' entry on the Erlang target, already precedented by glemy/io's own equivalent). deno task browser-check-platformer passes for real on its first run with no iteration needed (39 real requestAnimationFrame frames, a real held ArrowRight moved the captured player position past world-x 28, a real held-space jump moved it past world-y 20, 2 sounds played, and holding ArrowLeft from a fresh page load reached a real "You fell!" status). deno task browser-check and browser-check-breakout were also re-run for regression safety (CLAUDE.md's standing rule for anything touching glemy/game-shaped code) -- both still pass unchanged.
Consequences
glemy now has three complete, independently-launchable reference games (index.html/Tiers, breakout.html/Breakout, platformer.html/Platformer), each with its own real-browser verification script sharing only the genuinely game-agnostic launch/dev-server bootstrap. The captured-GPU-uniform-buffer world-position-verification technique tools/browser_check.ts originally built for one specific check (Tiers' click-to-spawn) is now confirmed reusable as a general pattern for 'did a real WebGPU-rendered entity move to roughly where real input should have put it' -- valuable precedent for a future game whose own real physics entity also has no DOM position to read directly. Phase 3 (feel-constant tuning, glemy-website catalog integration) is the only remaining item on this game's roadmap.