// education / guide

How to Build a Browser Game From Scratch

Ember Keep is a complete tower-defense game — waves, bosses, an economy, four upgradeable towers, sound — running live on this site. There is no game engine underneath it. No Unity, no Phaser, not even a <canvas>. Just React, SVG elements moved by hand, and sound synthesized from raw oscillators. This guide takes it apart, layer by layer, from the highest-level architecture down to single-attribute DOM writes.

Play Ember Keep firstthe game this guide dissects — two minutes of play makes every section clickplay →

Who this is for

You write software or run infrastructure for a living, but game programming feels like a foreign country: people there say sprite, game loop and scene graph like everyone was born knowing them. This guide assumes zero game-dev background. Every term is defined the moment it appears, and wherever a game concept has a backend or DevOps cousin — and it usually does — the analogy is spelled out. A game loop, it turns out, is just a reconciliation loop with better sound effects.

Why this codebase makes a good textbook

ZombieTowerDefense.js and a handful of support files implement the whole game with no game engine and no audio files — every sound is synthesized live from the Web Audio API. The first shipped version didn't even use image files: all art was inline SVG shapes. Later, AI-painted PNG artwork was layered on top without touching the engine — and that upgrade path is itself one of the best lessons in here (part 2). Building this unusually means every chapter also has to explain what a "normal" game would do instead — so you learn the general vocabulary and one concrete implementation at the same time.

The route

The cast of files

You'll meet these over and over. One file is the engine — the code that enforces the rules and draws the world. Everything else is data it reads:

FileRole
ZombieTowerDefense.jsThe engine. One React component holding the game loop, the renderer, input handling and the HUD — everything else on this list exists to be read or called by it.
td-config.jsAll gameplay tuning: tower stats, zombie stats, the wave generator, the economy. Balance changes happen here and nowhere else — like a config file your service reads at startup.
td-sprites.jsGenerated SVG artwork: one markup string per sprite plus its anchor metadata. Header says "do not hand-edit" — it’s a build artifact, like a generated API client.
td-sprites-elements.jsThe painted-art layer: AI-generated PNG illustrations that override the generated sprites at runtime, keeping the same size/anchor contract.
td-sfx.jsA synthesizer, not an audio player: arrows, cannons and zombie squelches built from Web Audio oscillators and noise at play time. Zero audio assets.
zombie-tower-defense.cssPage-scoped styling for the HUD, plus CSS keyframe animations for ambient effects (mist, embers) that run without any JavaScript per frame.

Ready? Start with the architecture — the one diagram that makes everything else in the game make sense.