← The game interface — first brush · all tasks

Android build is missing the whole interface — shell is DOM-only, APK ships the bare 3D world

done priority 1 estimate L

game-interface/004 · created 2026-08-11 · updated 2026-08-12

What

Kris played the live /play page (works — title screen, HUD, Ingredients panel all present) and then installed the APK on his phone: the 3D world runs, but none of the interface layer is there — no title screen, no HUD buttons, no Ingredients/Spells/Gear panel, not even the help bar. He suspected the UI had only ever been built as an HTML overlay rather than into the Godot project itself. That’s exactly right, confirmed by reading the actual architecture:

Deliverable 9’s own acceptance criteria (“title screen… HUD… Ingredients tab”) make no browser/mobile distinction — the APK not meeting them is a real gap against what was promised, not a scope question.

The fork this needs

Two genuinely different ways to close this gap:

  1. Wrap the existing web build in a WebView shell for Android, instead of exporting the raw Godot project. Reuses the shell, the Claude Design pass, and the card renderer/editor contract completely untouched — zero redesign. Downsides: WASM inside a mobile WebView is materially slower than Godot’s native Android renderer; touch input, fullscreen/back-button behaviour, and Android WebView quirks (version fragmentation) all need real verification, not assumption; app size grows (bundling the web build into the APK).
  2. Build the interface natively in Godot (Control nodes: title screen, HUD, tabbed stuff panel, card grid/modal) so one implementation ships identically on web and Android. Better native performance and input handling, no WebView involved at all. Downsides: the whole Claude Design handoff (docs/design/HANDOFF.md, the two .dc.html references) is HTML/CSS — none of it transfers directly to Godot’s UI system, so the visual pass has to be rebuilt by hand in-engine and now has two places that can drift (DOM shell for web, Control-node UI for Android) unless the web shell is later retired in favour of the same native UI running inside the Web export too.

RESOLVED by Kris (2026-08-12, planning session): option 2 — native Godot UI — is the direction, explicitly confirmed (“we want this correctly implemented in Godot — and well architected too”). The WebView wrap is rejected. The DOM shell’s UI layers get retired to a thin tap-to-play loader (Kris chose the gate over auto-loading the ~40MB engine on page open); the Godot Control-node scenes become the visual source of truth for the interface. The original assumption text follows for provenance:

Assumption (flagging, not blocking): defaulting to option 2 — native Godot UI — as the direction to prototype first, because “one implementation, both platforms” matches this project’s existing bias (world/’s whole reason for being one shared project is “movement code can never diverge between client and server by reimplementation drift” — the same argument applies to the interface). But this is a real architectural fork with a real cost (redoing the Claude Design visual pass by hand), not a mechanical fix, so whoever picks this up should read both options above before starting rather than take the assumption on faith — and Kris should get a chance to weigh in during review, since it resets which surface (shell/ DOM vs. Godot Control nodes) is the visual source of truth going forward.

Done

Both platforms show the same interface: title screen, HUD (health bar + Ingredients / Spells / Gear), tabbed stuff panel with the Ingredients grid and card modal, working identically on the live /play page and on a fresh install of the APK on an Android phone. Update game/README.md’s “Known limits” section either way — this stops being an undocumented gap once someone’s made the call.

Review

Kris installs the rebuilt APK on his phone and confirms the interface is there and usable one-handed in landscape, same as the browser version.

Built (2026-08-12)

The interface was rebuilt as native Godot Control-node scenes in land-of-lor/game/world/client/ui/ — title screen, HUD (press-hold labels, tap-to-move passthrough), stuff panel with the always-8-across grid, and the element card with all three rarity frames (legendary = animated foil shader) and the un-collected template. Architecture notes in land-of-lor/game/README.md: app.tscn root flow; player_state.gd is the deliberate MMOG seam (demo owned-set, placeholder health, signals) that server-backed accounts later replace; element_db.gd reads data/elements.json, synced from the canonical shell/elements.js by sync-elements.sh inside both export scripts. client_main.gd, the six shared .gd files, and the protocol are byte-identical; 64/64 pure-logic tests pass. The web shell is now a thin tap-to-play loader (Kris chose the gate over auto-download); the card editor + its HTML renderer stay as authoring tools (documented drift tradeoff: editor preview vs Godot render — data cannot drift). Verified end-to-end in a CDP-driven browser: loader → engine boot → native title → Start → live-droplet world with HUD, 1600+ remote entity updates streaming. New APK (27.7 MB, package au.com.cocreations.lor.game v0.0.1, lor2026-signed) uploaded to the droplet.

Pre-existing quirk noticed while verifying (NOT introduced here, present in the old poc web build too when connected): the client logs occasional “Parse JSON failed” console errors during live traffic — protocol-side, frozen code, harmless to gameplay; worth a look whenever the protocol next opens for changes.

View source in repository · also available as raw markdown.