● flagship WebGPU wasm32

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.

towers — crcbl
Starting…
Click the canvas first. A canvas has to hold keyboard focus to receive keys, and browsers will not start audio until you have interacted with the page. Clicking away pauses the game and lets go of whatever key was held — no platform sends the release for a key that was down when focus left.
Touch reaches the engine. A contact arrives as an ordinary pointer, and the first one is also the gesture a browser waits for before it will start audio. Whether this demo can be played with one is in its controls below — not all of them can. Switching tabs pauses the game and lets go of whatever was held: no platform sends the release for an input that was down when focus left.

controls

The waves arrive on their own. What you do is spend the purse.

There is no pointer or finger here yet. The build list is picked through with two keys, so a phone gets a field that plays itself — the waves arrive on the table's own clock and a finished run starts over. What a tap wants to land on is the build menu that arrives with this sample's pixel art, and a hit test written against the untextured list above would be thrown away with it.

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.

Open the console for the engine's log. The wasm module imports nothing, not even 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.