A synthwave roguelike brick-breaker. Geometry Wars chaos meets Breakout discipline.
Clear waves of neon bricks across four worlds, draft build-defining modifiers between stages, and lose all your balls to end the run. A Piercing + Chain + Explosive build plays completely differently from a Heavy + Magnetic + Curved one.
npm install
npm run devOpen the local Vite URL. Use arrow keys or WASD to move the paddle, Space to launch.
| Input | Action |
|---|---|
| Arrow keys / WASD | Move paddle |
| Space / A button | Launch ball |
| Esc / Start | Pause |
| 1–5 | Pick draft option or class |
| E | Reroll draft |
| R | Restart run |
` |
Toggle bounce-tuning debug overlay |
npm run dev # Dev server with hot reload
npm run build # Production build → dist/
npm test # Run all tests (vitest)
npm run typecheck # Type check without emittingRun a single test file:
npx vitest run src/systems/BallSystem.test.ts- PixiJS 8 — WebGL renderer
- TypeScript — strict mode
- Vite — dev server + bundler
- Vitest — unit tests (50 tests across 7 suites)
No game framework. The game loop, physics, and collision are hand-rolled.
The game runs on a fixed 240Hz logic timestep decoupled from render rate. All gameplay randomness goes through a single seeded PRNG (mulberry32), making every run fully reproducible from its seed — required for daily seeds and leaderboards.
ticker → input.poll() → fixed step loop → render
↓
BrickSystem → PaddleSystem → BallSystem
→ ScoreSystem → PickupSystem → ParticleSystem
BallSystem writes FrameEvents (brick breaks, paddle hits) each step; downstream systems react to those events rather than querying state directly.
See CLAUDE.md for a deeper architecture guide and DESIGN.md for the full game design document.
| World | Theme | New brick types |
|---|---|---|
| 1. Grid Dawn | Sunrise on the neon horizon | Standard, Reinforced |
| 2. Vector Reef | Underwater synthwave | Prism |
| 3. Chrome Highway | Endless night drive | Mirror, Phase |
| 4. Cathedral | Massive geometric monolith | Magnet, Core |
MIT — see LICENSE.