About the project

Inspiration

We wanted to see if a game could have real conversations — not dialogue trees, not "pick option A/B/C," but NPCs that actually listen and talk back. The deep ocean felt like the right setting: claustrophobic, full of people who don't trust each other, where what you say matters more than what you shoot. Games like Disco Elysium and Subnautica lit the fuse; the rest was asking "what if every NPC had a brain running on your laptop?"

What it does

Abyssal Genesis is a top-down deep-sea RPG where you wake up at the bottom of the Hadal Trench and have to ascend five zones to reach the surface — through a captain who left you to die. Along the way you:

  • Talk to 20+ NPCs powered by a locally-run LLM, each with their own role, faction, fears, and memory of your trust
  • Fight shark packs, ruin sentries, and brood predators with a heat-based weapon system (no ammo, just overheating)
  • Solve Among Us–style wire-match and pulse-sequence panels at tactical POIs
  • Decrypt Caesar-ciphered slates recovered from enemy nests using in-world clues
  • Ascend only after clearing each zone's quota (1 combat + 1 tactical + 2 verbal missions)
  • Confront a final gatekeeper whose fate — peaceful passage or boss fight — is decided entirely by a stance-scored branching conversation

How we built it

  • Phaser 3 for the 2D engine, TypeScript end-to-end for type safety across scenes/systems/entities
  • Zustand as a global reactive store for faction standings, flags, quest state, and player stats
  • Ollama + llama3.2:3b running locally for NPC dialogue — zero latency, zero API cost, zero data leaving the player's machine
  • Scene-based architecture: separate Phaser scenes for World, Dialogue, Tactical puzzles, Cipher, FinalStand, UI HUD, and Boot
  • Data-driven quests and POIs — every mission is a single registered object defining zone, category, steps, and rewards; the gate system just counts completions per category
  • Streaming dialogue text with a dynamic auto-resizing conversation box so responses never overflow

Challenges we ran into

  • Keeping LLM output in-character: the model wanted to break kayfabe constantly. We solved it with tight per-NPC system prompts (role, faction, goal, fears, speech tone) plus a personality-based fallback layer when Ollama isn't reachable
  • Zone-gating deadlock: story quests required ascending as their final step, which would have blocked the gate on itself. Fixed by scoring gate progress on the first step, not full completion
  • HUD overlap with dialogue: left and right HUD panels kept bleeding through the conversation box — solved by toggling UIScene visibility on every sub-scene
  • Long NPC replies overflowing the text box: rebuilt the dialogue layout to measure text height every frame during streaming, resize the box upward, and trim-from-start with an ellipsis when truly oversized
  • Making combat feel like it belongs in an RPG, not a bullet-hell: removed ammo, added heat-based overheat lockouts, and tuned enemy spawns to small arena encounters tied to POIs

What we learned

  • Local LLMs are genuinely viable for game NPCs — llama3.2:3b responds fast enough on consumer hardware that it feels interactive, not laggy
  • Data-driven design pays off fast: once the POI/quest schemas existed, adding a whole new cipher mission type took ~100 lines across one new scene
  • Scene visibility is the cheapest way to build modal UIs in Phaser
  • A conversation can be a boss fight if you score it right

What's next

  • More cipher variants (substitution, Vigenère, visual pattern puzzles)
  • Persistent save/load so faction reputation survives restarts
  • More verbal missions with stance-scored branching like the final encounter
  • Voice synthesis for NPC lines (Piper running locally alongside Ollama)

Built with

  • TypeScript (strict mode, end-to-end)
  • Phaser 3.88 — 2D game engine, arcade physics, scene system
  • Vite 5 — dev server + production bundler
  • Zustand — reactive global state store
  • Ollama — local LLM runtime
  • llama3.2:3b — on-device language model for NPC dialogue
  • HTML5 Canvas / WebGL — Phaser rendering backend
  • DOM overlays — for text input, dialogue chips, and cipher decode UI layered over the canvas
  • Node.js + npm — build toolchain
  • Aseprite / pixel-art sprite packs — tilesets and UI frames
  • Web Audio API (via Phaser) — depth-reactive ambient soundtrack and SFX

Built With

Share this project:

Updates