Towers
Creeps walk a lane, towers shoot them, kills pay for the next tower. Build nothing and the field overruns you, because the table releases more creeps than the team has lives. The interesting part is not on screen: every build and every wave is a command a server validates, and this page is running both halves of it.
controls
The waves arrive on their own. What you do is spend the purse.
- Pick a build plot from the list ← →
- Build a tower on it. The server refuses a plot that is taken and a purse that is short. B
- Send the next wave now rather than waiting the build phase out N
- Throw the run away and start again R
- Pause and resume Esc
- Fullscreen F11
- Debug overlay F3
- Debug console `
- Pause, fullscreen and the debug overlay keys — unless a control for them is listed above
- Debug console, and its on-screen keyboard the CONSOLE button, once you have touched the canvas
what is actually running
Solo is the co-op build with one player in it.
Nothing here is a shortcut for being alone. Pressing B does not place a tower; it seals the plot number into a command and hands it to a server, which decides whether the plot is free and the purse is deep enough and only then makes one. The same is true of the wave and of the restart. On this page the transport between the two is the engine's in-memory loopback, and in a co-op session it is a wire — the game on either side of it does not change, which is the whole reason a tower defense was chosen as the sample that proves multiplayer.
The debug panel counts the refusals. It reads zero while you play honestly, and climbs the moment you ask for a plot that is already built — which is the difference between a client that asks and a client that decides.
The combat is three physics queries and no special cases. A tower finds a target with one sphere overlap, and the interesting half is the filter: the same query hands it the ground slab and the exit volume, so a tower that took the first thing it touched would shoot the floor. A bolt finds its creep with a swept sphere, because a bolt covers more ground in a tick than a creep is wide and a test at either end of that tick sees nothing. And a creep reaches the exit by walking into a trigger volume — non-solid, so every sweep and every ray passes straight through it and only an overlap reports it, which is exactly what a "did anything get in here?" volume wants.
This slice is one map, one tower and three waves. The plan asks for three tower types with an upgrade tier each, three creep types, ten waves, pixel art, spatial audio and a map authored in an editor that does not exist yet. None of that is here. What is here is the loop, end to end, in the same build that runs natively — so the wasm target cannot quietly rot while the rest of it is written.
The field is a lane, a ground slab, five build pads and a box per creep, every one of them a primitive generated in code from a table of constants. It draws through the three arms a browser resolves to by construction — draw arguments generated per batch, textures bound as array pages, lighting rasterised — and the panel says which, because a demo that reports the path it took is a demo you can believe about the one it did not.
console.log, so log lines are queued
inside wasm and drained by the page each frame. crcbl.audio(),
crcbl.saves() and crcbl.logLevel(4) are there too.