Neon Phaser: Cyberwave Assault
Neon cyberpunk shooter with wave-based combat. Phaser + Express, now playable on-site.

TL;DR
- 100% client-side — Express only served statics, dropped for this site.
- Seven Phaser scenes, modular classes/managers.
- Canvas + CSS background composition behind the game canvas.
- Wave-based enemy spawning + collision data tables.
- Pause / game-over / settings as proper scene transitions.
Architecture
Vanilla Phaser, no framework wrapping. Static host, no API.
Screens
Menu — neon city background
The title screen runs three composed layers: Phaser canvas in front, a regular HTML5 canvas behind it drawing the perspective grid + rotating neon cubes, and a particle layer on top of that. Compositing in CSS instead of Phaser keeps the game canvas focused on gameplay.
Story scene — animated dialog frames
After the menu the game cuts to a narrative scene with hand-drawn cyberpunk frames. Skip/Next live on the canvas. This is one of seven Phaser scenes — preload, menu, story, game, pause, game-over, settings — each in its own file.
Problem
I wanted a side-scrolling cyberpunk shooter with the look of an arcade cabinet — fast, neon-glow, with a hand-built parallax background and an honest 60fps Phaser game loop. No engine framework around it, no build step. Just Phaser, vanilla JS modules, and a static server.
Approach
Phaser 3 client served by a one-file Express static host (no API). Seven Phaser scenes — preload / menu / story / game / pause / game-over / settings — each in its own file. Class-based game objects (Player, Enemy, PowerUp), separated managers, data files for enemy patterns. The background is its own thing: a Canvas-rendered perspective grid + rotating 3D neon cubes + a CSS particle layer, all behind the gameplay.
Deep dive
Background composition without the engine
The Phaser canvas runs the gameplay. Behind it sits a regular HTML5 canvas (`#cityCanvas`) rendering a rotated perspective grid + animated neon cubes in pure 2D context math, and an absolutely-positioned `#particlesContainer` with CSS-animated DOM nodes. Compositing three layers in CSS is cheaper than asking Phaser to also render the city.
Why vanilla JS — and what that cost
No bundler, no TS, no React. The whole game is ES modules loaded as `<script type='module'>`. Build is instant, dev is just refresh. Cost: no type safety, no tree-shaking, no per-route splitting. For a game-canvas app that's a fair trade. The trade-off doesn't hold once you add real UI chrome — that's why Aether Drift (next-gen of this) pulled in Next + React for the shell.
Outcome
Feature-complete demo. Now embedded on this site as a static workspace package — the Express server was replaced by serving the public/ folder directly, since it had zero backend logic.
Related


