Devlog #006 — The Living Grid: A Stage That Reacts
The arena floor in PULSE//ZERO is not a backdrop — it is a single shader that listens to the whole game and answers in light. Here is what the Living Grid is, why a reactive stage is the thing that makes the game sing, and how it works.
Across the last few entries we’ve introduced the company you keep in a run. Devlog #002 was the cast — the five enemy archetypes you fight. Devlog #003 was the conductor — the Adaptive Director that decides who shows up and when. And Devlog #005 was the headline acts, the mini-bosses that punctuate a run. This entry is about the thing they all perform on: the Living Grid, the arena floor itself.

The floor is the one element that touches everything — here it deforms around the mass sitting on it.
Way back in Devlog #001 we promised the whole vertical slice existed to prove the grid carries the game. We said we’d come back and open it up. This is us finally delivering that deep-dive.
Why a reactive stage matters
A twin-stick arena shooter is, mechanically, a lot of dots moving on a plane. The difference between that reading as a spreadsheet and reading as a place is feedback. Every kill, every dash, every bomb has to land somewhere — and if the only thing that reacts is the enemy that died, the world feels inert. The floor just sits there.
So we made the floor the game’s shared feedback surface. The grid is the one element on screen that touches everything: it sees the player move, it sees projectiles connect, it sees a combo climb, it sees a boss arrive. When the whole arena flexes in response to what you do, the game stops feeling like objects on a background and starts feeling like a system you’re inside of. That’s the thing that makes it sing.
One shader, many signatures
The Living Grid is a single canvas-item shader. There are no mesh vertices being pushed around, no particle systems faking ripples — the shader draws the grid lines analytically and displaces them in the fragment stage. One draw call, which matters for keeping it smooth on modest hardware.
The trick is that the GPU side stays dumb and the CPU side stays simple. The grid node owns a small pool of events — up to 32 at once — and each event is just a position, an age, a strength, a radius, a speed, and a type. Every gameplay moment that should disturb the floor pushes one event into that pool, the pool is uploaded to the shader as a few flat arrays, and the shader sums their influence per-pixel. The design goal was that adding a new kind of grid reaction is a new event type and one line of code, never a rewrite.
Crucially, the grid never reaches out to read game state. Everything arrives over signals — it listens, it never asks:
GameEvents.player_dashed.connect(_on_player_dashed)
GameEvents.bomb_exploded.connect(_on_bomb_exploded)
GameEvents.enemy_killed.connect(_on_enemy_killed)
GameEvents.multiplier_changed.connect(_on_multiplier_changed)
GameEvents.mini_boss_spawned.connect(func(_id): _on_boss_arrival())
That one-way wiring is the same separation-of-concerns idea that runs through the enemies and the Director: no system calls methods on the grid directly. It just publishes what happened, and the floor decides how to show it.
Different events, different language
The reason a reactive stage works as feedback and not just decoration is that each kind of event has its own distinct ripple signature. The player learns to read the floor without ever being told to. A few of the event types:
- Wake — a soft, persistent well that follows the player. It’s the only permanent event, a gentle dent in the floor that says you are here.
- Ripple — a small oscillating ring for the routine stuff: an enemy death, a pickup, a projectile landing. Quiet, frequent, reassuring.
- Shockwave — a sharp compression ring that pulls the grid inward, used for dashes and bombs. It reads as force, not just light.
- Pulse — an oscillating area bloom that swells and fades, layered under the bigger beats (a bomb’s secondary wash, a grid surge) to give them body.
- Surge — a full-arena radial flood, the loudest thing the floor can do. We reserve it for the big beats: a mini-boss defeated, a boss arrival.
Those last two are worth dwelling on, because the grid telegraphs as well as celebrates. When a mini-boss spawns we fire a heavy inward shockwave plus a surge from arena centre — the floor itself announces the threat a beat before the fight proper begins. Reward and warning use the same vocabulary, just aimed differently.
The arena heats up
Beyond discrete events, the grid carries a continuous read of how aggressively you’re playing. As your combo multiplier climbs, two things happen: the whole grid brightens, and its colour shifts from cool cyan toward a hot magenta.
func _on_multiplier_changed(mult: int, _timer: float) -> void:
var shift: float = clampf(float(mult - 1) / 15.0, 0.0, 1.0)
_mat.set_shader_parameter("color_shift", shift)
_mat.set_shader_parameter("global_intensity", clampf(0.88 + mult * 0.075, 0.88, 1.85))
At high distortion those colours push past 1.0 in their channels and bloom under HDR, so a hot streak doesn’t just score more — the arena visibly runs hotter around you. It’s the difference between a number going up and a feeling going up.
Restraint is part of the design
One thing we learned building this: a reactive floor wants to react to everything, and that way lies noise. We trialled centre-out pulses for combo milestones, unlocks, grid surges, and directive completions — and pulled every one of them back out, because they read as intrusive rather than satisfying. The code still carries those handlers as deliberate no-ops, a little scar tissue reminding us that the grid earns its loudest gestures by mostly staying calm. There’s also a reduced-effects mode that drops the subtler events entirely, for players who want the readability without the swell.
Next time
The grid heats up with your combo, and so does the music — the two are coupled. The dynamic soundtrack reads the same intensity the grid does, layering and swelling as a run escalates, and that’s Devlog #007. The stage has a score, and we’ll show you how it’s wired.
As always: we build in the open.
- pulse-zero
- design
- shaders