We built Bomber Blast as a TypeScript monorepo whose core is a single deterministic rules engine with no DOM dependencies, used by the browser, the server and the bots alike.
Key design decisions
- One engine, three uses.
step(state, inputs) advances the game by one fixed 60 Hz tick. Single-player runs it in the browser, the Socket.io server runs it as the authority, and the client re-runs its movement code to predict the local player. Rules cannot diverge between modes.
- Chain reactions in one tick. A detonation queue raycasts each blast and pushes every bomb it reaches, so a whole chain resolves before anyone moves again. Destroyed bricks burn for the flame's lifetime and only then roll the seeded power-up drop table, which keeps replays deterministic.
- Bots that plan around time. A danger map stores, per tile, the seconds until it explodes, with chain reactions propagated to the earliest fuse and upcoming Sudden Death tiles included. Escape routes are a breadth-first search that only enters tiles the bot can cross before they burn, and a bot drops a bomb only if such a route exists.
- Intents, not positions. Clients send direction and button presses with a sequence number. The server applies them, rate-limits and collapses backlogs, and broadcasts compact binary snapshots at 20 Hz. The client replays unacknowledged inputs on top of each snapshot and interpolates remote players 100 ms in the past.
- No asset pipeline. Sprites are painted with Canvas 2D at the current tile resolution and packed into one atlas; sounds and music are synthesised into PCM. The game stays sharp at any resolution and the client is about 400 KB gzipped.
- Input as an abstraction. Keyboard, Gamepad API and an on-screen joystick all produce the same per-tick intent, and the most recently used device takes over automatically.
Architecture
packages/shared holds the rules engine, the AI and the protocol (zod schemas for lobby JSON and a DataView codec for snapshots). apps/server is Express plus Socket.io with a room registry: codes, public listing, ready-up, host hand-over and garbage collection of stale rooms, each room running its own authoritative loop. apps/client is Vite and Phaser 3 (WebGL with Canvas fallback) behind a responsive HTML/CSS shell for menus, lobby, HUD and results; drivers feed the renderer from a local simulation or from the network.