Type a prompt. Get a world. Explore it in ASCII.
Terminus is a first-person 3D exploration and survival game where every pixel is an ASCII character. Describe a world in natural language, and the engine procedurally generates a unique landscape with blended biomes, seasonal weather, enemy encounters, and AI-composed music — all rendered as living, full-color ASCII art at 60fps in your browser.
- ASCII rendering engine — Three.js renders a hidden 3D scene; a custom pipeline converts pixels to colored glyphs via luminance mapping, edge detection, foveated quality, and temporal stabilization
- Prompt-driven worlds — Type a description like "frozen island with volcanic canyons" and get a unique, explorable world
- 9 biomes — Plains, forest, desert, tundra, island, swamp, canyon, volcanic, mythic-crystal — each with unique terrain shaping, colors, and vegetation
- AI music — Each world gets a unique soundtrack generated via Google Lyria, shaped by biome and prompt context
- Seasons & survival — Spring/summer/autumn/winter cycle with temperature, stamina, health, and thermal stress
- Combat — Enemy dog packs that patrol and attack; scrap pistol with bullet tracers and muzzle flash
- Share codes — Every world encodes into a compact code; paste it in to get the exact same world
| Feature | Gemini Capability | How It's Used |
|---|---|---|
| Biome selection | Gemini 2.5 Flash | Reads world prompt and selects 2-3 biomes from the catalog |
| World music | Lyria via Vertex AI | Generates a unique looping soundtrack per world based on biome + prompt context |
# Clone and enter
git clone <repo>
cd terminus
# Install dependencies
npm install
# Set up environment (optional, for AI features)
cp .env.example .env
# Edit .env and add your GEMINI_API_KEY
# Run
npm run dev- Write a prompt — Describe your world (e.g. "swampy forest with frozen coastlines")
- Generate — Click Generate or hit Ctrl+R to reroll the variant seed
- Explore — Click to enter, move with WASD, look with mouse
- Survive — Manage stamina and health across biomes and seasons
- Fight — Click to shoot enemy dogs; E to interact with terminals and switches
- Share — Copy the share code and send it to anyone
| Control | Action |
|---|---|
| WASD | Move |
| Mouse | Look |
| Shift | Sprint |
| Space | Jump |
| Click | Shoot |
| E | Interact |
| Escape | Pause |
| Ctrl+R | Reroll world variant |
- Language: TypeScript (~10,600 lines)
- 3D: Three.js
- Bundler: Vite
- Tests: Vitest (10 test files)
- AI: Gemini 2.5 Flash, Google Lyria (Vertex AI)
- Dependencies: Zero runtime dependencies beyond Three.js
terminus/
├── src/
│ ├── game/
│ │ ├── app.ts # Game loop, physics, UI, combat
│ │ ├── input.ts # Keyboard/mouse via pointer lock
│ │ └── collision.ts # Iterative cylindrical collision
│ ├── render/
│ │ └── ascii.ts # WebGL → pixel readback → ASCII mapping
│ ├── world/
│ │ ├── worldManager.ts # Chunk streaming, mesh creation, enemies
│ │ ├── worldGenerator.ts # Base procedural terrain generator
│ │ ├── biomeWorldGenerator.ts # Biome-aware terrain with blending
│ │ ├── spawn.ts # Safe spawn point selection
│ │ └── noise.ts # Fractal & value noise functions
│ ├── biome/
│ │ ├── catalog.ts # 9 biome template definitions
│ │ ├── spec.ts # Prompt parsing, share codes, compilation
│ │ ├── season.ts # Seasonal cycle state machine
│ │ └── geminiBiomeService.ts # Gemini API biome suggestion
│ ├── audio/
│ │ ├── lyriaRealtimeMusicService.ts # Lyria API integration
│ │ ├── webAudioMusicPlayer.ts # Web Audio playback
│ │ ├── worldMusicController.ts # Music lifecycle management
│ │ └── musicPrompt.ts # Biome-aware prompt builder
│ ├── interaction/
│ │ ├── interactionSystem.ts # Raycasting target detection
│ │ └── rules.ts # Inspect/toggle logic
│ ├── utils/
│ │ ├── hash.ts # Deterministic hashing (FNV-1a, mix3)
│ │ └── rng.ts # Seeded LCG random number generator
│ ├── config.ts # All tunable parameters
│ ├── types.ts # Shared interfaces
│ └── main.ts # Entry point
├── tests/ # 10 test files
├── vite.config.ts # Gemini + Lyria dev proxies
└── .env.example # Environment template
- Prompt → Local parser (or Gemini) selects biomes and weights from the catalog
- Compile → Biome spec + variant seed → deterministic world seed, season epoch, layout plan
- Generate → Fractal noise + biome-specific terrain shaping (dunes, gorges, archipelagos, volcanic ridges) → heightmap chunks
- Render → Three.js draws the 3D scene to a hidden canvas → pixel buffer readback → luminance + edge detection → glyph ramp mapping → colored ASCII output
- Adapt → Frame timing drives adaptive quality scaling; foveated rendering boosts center detail; temporal blending stabilizes flicker
- Music → Biome context builds a Lyria prompt → Vertex AI generates a unique looping track → Web Audio playback
Terminus is built around Google's AI stack:
- Gemini 2.5 Flash — Interprets natural language world prompts and selects optimal biome combinations from the catalog. Powers the prompt-driven world generation pipeline.
- Google Lyria (Vertex AI) — Generates unique, looping background music for each world. The music prompt is dynamically built from biome context, seasonal state, and user vibe input.
- Vertex AI — Hosts the Lyria model endpoint. Supports configurable project, location, and model selection via environment variables.
- Google Cloud — Bearer token auth for Vertex AI access. Compatible with
gcloud auth print-access-tokenworkflow.
The Vite dev server includes built-in proxy plugins for both Gemini and Lyria APIs, keeping API keys server-side during development.
- 3D: Three.js
- AI: Google Gemini, Google Lyria
- Bundler: Vite
MIT
