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
UIScenevisibility 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
Log in or sign up for Devpost to join the conversation.