Live

For What Lies Beneath, playable

The Godot web export, running on a plain static host

The game itself — a from-scratch tactics game built in Godot, exported to the web and served as files. This is the creative result the rest of the portfolio’s instruments exist to build: the DAW’s loops, the auditioned effects, and the workshop’s verdicts all point here. Click the canvas, then Enter confirms, WASD/arrows move, Esc backs out. The path through it: faction select, the branching march map, then a battle on destructible terrain with the action menu and unit stats live.

Read it as what it is: an early preview of a game being attempted, not a finished one. The look is development graphics — deliberately programmatic — and many screens are simple dev placeholders holding a slot for scenes that aren’t built yet. What’s further along is the systems underneath them. And one production detail worth naming plainly: some of the billboard sprites are AI-generated retro pixel graphics, produced with Adobe Firefly Services in the character-art pipeline.

The build ships its own workbenches — jump straight into one:

  • FX Lab/ picks a spell, Space casts it, a click casts at the tile you point at. Tab flips the side panel to the liquid studio: right-click pours water onto the terrain (Q1Q4 switch to poison, lava, swamp). Further Tabs reach fog, trees, wind; Q/E orbits the camera.
  • Sound Lab/ cycles the game’s sound effects, Space or a click plays one, number keys jump categories.
  • UI Lab — the look-and-feel bench: W/S/Enter drive the menu cascade, drag the bars bottom-left to re-theme every widget live.

The same jumper is available anywhere in the build from the gear top-right (or Ctrl+D).

Run it full-page →

It needs no cross-origin isolation, and none is configured. The common expectation is that Godot Web requires SharedArrayBuffer, therefore COOP/COEP headers, therefore a service-worker shim on a static host. Measured on a server sending no cross-origin headers at all, crossOriginIsolated is false and SharedArrayBuffer is undefined, and the export boots and plays anyway: a single-threaded Emscripten build with no GDExtension never asks — the loader’s references are feature detection, not requirements.

This export is dated 2026-06-12, about ten weeks behind the project’s current tip, and it runs silent — the music directory was not packed, and the engine log says so: WARNING: [music] no tracks in res://music. Measured at 32 fps at 1280×800 during a battle (one three-second sample in one browser on one machine, not a benchmark). Godot 4.6.3, 63 MB total, the largest single file a 37.7 MB index.wasm.

The instrumentation used to drive and inspect it from outside: the devtools protocol. The source is a private personal-project repository.