A Rainboids design diary: 46 rule-rewriting passives, 12 ship skins, a reworked power economy, the skeleton of scripted bosses — and a day spent choosing restraint over cleverness.
A Day That Grew a Layer
There are days where you ship one feature, and days where a whole layer of the game snaps into place. May 24th was the second kind. By the end of it Rainboids had grown an entire build system — Passive skills that rewrite how a run plays, acquired two different ways, all wired and tested — plus a wardrobe of twelve animated ship skins, a font system, a rebuilt power economy, and the chassis for scripted multi-phase bosses.
The version numbers undersell what the day was about. Roughly forty-five of them shipped, from 6.115.1 to 6.159.0, but a changelog reads like a list of effects when the interesting part is the causes. Almost every decision came back to one question we kept putting to each other: what’s the cleanest solution here? Not the most clever, not the most feature-rich — the one that won’t quietly rot the game six months from now.
This post is about those decisions, because the reasoning behind them is more durable than any single feature. A lot of the day was spent saying no to good ideas because a cleaner one was hiding behind them.
The Unglamorous Decision: Naming
Before a single passive could exist, we had a vocabulary problem. The game already used the word “passive” for two different things: the numeric stat boons you draft after a wave (more crit, more health, more dodge) and the same stat families bought permanently with Stat Points. And the backlog reserved it for a third, planned concept — item “traits” and “keystones,” which were rule-changers rather than numbers.
The Passive Skills we wanted to build were the rule-changers. So the word was already triple-booked, and the thing it was most strongly booked for was the least interesting one: stat sticks. You cannot design a system cleanly while its central noun points at three concepts at once.
We talked the fork through in prose before touching code. The options were to rename the stat pool and free the word, or to invent a fresh name like “Relics” and leave the existing stat code alone — a clean namespace versus less churn. We chose the rename, and went further than the first draft proposed: drop both loaded words. The stat pool became, simply, Stats. Stats are stats. “Passives” now means exactly one thing — build-defining rule-modifiers. It’s the least exciting commit of the day and arguably the most important, because everything downstream depended on the word meaning one thing.
One Registry, Two Doors
The biggest architectural call was refusing to build the same thing twice. The backlog had planned item traits and keystones as a separate, item-bound system. But those were obviously the same kind of thing as the new Passives — rules that change how the run plays. Building two parallel systems would have meant two implementations destined to drift apart and contradict each other.
So we built one registry with two acquisition channels. Each passive entry declares where it’s allowed to live — an equip slot, a roll on gear, or both — and the same effect fires regardless of how you obtained it. Equip Glass Cannon in a slot, or roll it on a god-tier helmet, and you get the identical hook and the identical behavior. There is exactly one place a rule-change is defined and exactly one place it’s consumed. Every duplicate system you avoid is a future contradiction you never have to debug.
One door we deliberately did not use was the card system. Rainboids already drafts powerup cards that amplify your equipped weapons and abilities, and it would have been easy to deliver passives the same way — pick a card, get a rule-change. We rejected it on purpose. Cards amplify what you already chose; passives rewrite the rules. Mixing the two muddies both: every card pick becomes a tense “is this a number bump or a build-defining swing?” decision, and the passive layer loses its identity as a deliberate, gold-bought, swappable commitment. An earlier draft even floated “fallback cards” and “economy cards” to pad out long runs; we called that a wrong turn and deleted it. Cards amplify, passives rewrite, and the two never share a channel.
Building a System Without Breaking the Game
The Passives system shipped in tiny increments — a foundation phase, then twenty-eight content batches, most of them one passive per commit, each with its own unit test. That cadence is only possible because of a single discipline that recurs all over the day’s work: the guarded no-op.
Every passive’s effect is written so that without the passive equipped, the code path is byte-for-byte what it was before. The hook checks whether you have the passive and otherwise falls straight through to the existing behavior. Adding Vendetta, which makes the last enemy to hurt you take extra damage from you, touches nobody who hasn’t equipped Vendetta. The multiplier passives multiply by one when absent. This is why the foundation commits could ship with the honest note that there was no player-facing change yet: we wired the entire substrate — the equipped-passive state, the active set, the slot-unlock logic, the aggregator that folds numeric modifiers into the existing stat getters — while the game played exactly as it had the day before. The system was fully load-bearing before it carried any load.
The same pattern closes the day. The boss phase-script runner is a complete engine for multi-phase bosses: ordered phase gates, an on-enter callback that fires exactly once and in order even when a single burst of damage blows past several thresholds at once, and a brief invulnerability window during transitions so a phase can’t be skipped by overkill. And it ships as a no-op for every enemy in the game, because none of them carry a phase script yet. Shipping an inert engine sounds pointless until you remember that the risky part is the control flow, not the content. We proved and tested the hard part before any boss depends on it. The ten scripted bosses bolt onto a chassis that already works.
The Fear That Shaped the Slots
The question “how many passives can a player stack?” sounds like a tuning knob. It’s actually the whole design, because passives rewrite rules, and rules that stack without limit produce degenerate builds — the one combination that trivializes everything, that everyone copies, that makes the other forty passives pointless.
We circled this across several rounds of the design. Early drafts floated six to eight slots. But once we committed to gear also granting passives, the arithmetic changed: a maxed loadout could combine equipped slots with gear rolls into something close to ten simultaneous rule-changes. So the slot cap had to come down to keep the total honest. We landed on a maximum of five equipped slots, opening progressively over a run so that length itself feels like a power ramp, plus a keystone budget of two — at most two build-defining keystones equipped at once, with the smaller modular passives unlimited.
Gear, meanwhile, only ever rolls the modular, additive passives; a keystone appears solely as a rare top-tier chase roll, and even then it doesn’t count against the budget. That rule has an almost emotional justification we wrote down: you should never roll “can’t crit” onto a helmet by accident. Glass Cannon and Purist are choices you opt into knowing the downside. Bricking your build via a loot drop isn’t risk and reward, it’s just bad luck, so the punishing keystones stay where you consciously equip them and gear only hands you things that feel good to find.
Underneath all of it sits a stated philosophy: ship tight, loosen from data. Five slots and two keystones is conservative. Raising a cap after playtest is a one-line change; clawing back an overpowered launch costs you a community’s trust. And the structural backstop is unbounded enemy scaling — the threat is designed to outpace your stack, so there’s no plateau where a degenerate build coasts forever.
Making Invisible Systems Visible
Most passives are a number change at a hook point. Four of them were genuinely hard, and they share a single problem: the mechanic worked, but the player couldn’t see it working. They shipped as effects first and then earned a dedicated polish pass, because half the work on a “complex” passive turned out to be rendering, not logic.
Gravity Well pulls enemies toward your reticle. The first version pulled them onto the exact aim point, where the per-frame separation code made them overlap-fight into a flickering dot — technically grouped, visually a glitch. The fix was a small dead-zone: enemies ease to the edge of a settle ring and stop, forming the loose cluster the passive actually promises, wrapped in a violet pull-field so you can see the well doing its work. Eye of the Storm slows nearby enemies while you hold still, which is invisible by definition — a stationary stance with no tell. We drew a calm bubble at the slow radius that appears only while the slow is live, and pulled the “are you holding still” check into a single shared function so the gameplay and the visual read from one source of truth.
Afterimage fires a bonus volley from the spot you dashed away from. The trick is that at the instant the dash triggers, the ship is still at its origin — the burst velocity integrates a frame later — so firing right then spawns the shots from where you left, with no persistent entity needed. But those bonus shots had no visible source as the ship streaked off, so now a fading violet ghost of the ship lingers at the origin. Twin Cast fires power weapons twice, and a silent double just looks like more damage, so the second cast’s muzzle flare tints a distinct phantom-violet — a clear “echo fired” tell. The implementation detail that mattered there: the half-damage second shot is a cloned configuration, never a mutation of the shared weapon data, because mutating the shared config once would poison every future cast.
The common lesson across all four is simple enough to put on a wall. A mechanic the player can’t perceive isn’t a feature; it’s a rumor.
The Restraint of Cosmetics
Twelve fully animated ship skins landed, from Apex with its counter-rotating intake and vectoring nozzles to a Wraith that shimmers as it cloaks, a Battlecruiser whose cannon spools up with your live energy meter, and the restored classic blue fighter from earlier versions. A new Hangar screen lets you pick them with a rotating preview. The interesting decision, though, is one we didn’t make.
There was a real temptation to give skins a dual collision radius — a small damage core inside a larger physics hull, the classic bullet-hell trick where your visible ship is bigger than your hittable point. We rejected it, and the reasoning is subtle enough to be worth recording so a future session doesn’t “fix” it. Rainboids has solid bodies — asteroids and rammers — that bounce off the ship, and the bounce fires at the visual radius. If the damage core were smaller than the bounce radius, the bounce would deflect a rammer before it ever reached the core, so contact damage would become rare and inconsistent. The bounce would effectively shield the core. Ramming has to stay reliably dangerous, so damage and bounce must remain married to a single radius.
Which yields the actual rule: every skin shares one fixed collision radius and changes only the hull drawing. The choice is purely cosmetic, by design. There is no “meta” skin, none that’s secretly smaller, no gameplay tax for picking the one you think looks best. The cleanest meta for cosmetics is no meta at all. The renderer keeps all the shared feedback effects — muzzle flash, hit flash, charge glow, level-up aura — and hands only the hull to the active skin, so the skins can’t accidentally diverge on the things that actually matter.
The font system carries the same restraint in a smaller package. Two style variables drive every menu and overlay, with a roster of nine faces, and the three modern ones are bundled with the build rather than pulled from a content network, so nothing sneaks an external dependency into a game that ships offline. But the canvas-drawn text — the title, the heads-up display, the target labels — stays in the pixel typeface, always. That isn’t laziness; it’s identity. Settings exist to make the menus comfortable to read, not to let you sand off the game’s face. Knowing which surfaces to leave untouched is as much a design choice as deciding which ones to open up.
The Energy Rework
The power-weapon economy got rebuilt. It used to be a meter you earned by landing hits; now it’s a charge that regenerates on its own, filling from empty in about twelve seconds, and every power weapon fires the instant you’ve banked enough. That second half quietly retired the old hold-to-charge wind-up on the charge shot, folding it into the same rule as everything else.
Unifying the firing rule across all power weapons is the cleaner meta because it’s one thing the player internalizes once, rather than “most powers work this way, but this one is special and you hold it.” A single rule beats a rule with an asterisk almost every time, even when the asterisk was someone’s favorite mechanic.
The rework also gave the ship a voice. The hull now visibly charges as the meter fills, with a ready ring once a shot is affordable and a bright pulse at full, and both the nose ring and the heads-up sphere mirror the meter, complete with a numeric readout and a gold flash the moment a shot becomes affordable. The resource went from an invisible accountant’s number to something you feel building under your hands.
The Difficulty Problem We Chose Not to Solve Yet
The biggest design arc of the day mostly didn’t ship, and that restraint is the point. There’s a planned phase for run difficulty, and watching it evolve across several rounds of revision is a case study in changing your mind on purpose.
The first idea was conventional: the player picks a difficulty tier, which applies fixed multipliers to enemy health, damage, and loot. We scrapped it. Difficulty shouldn’t be a number you pick once; it should be an adaptive director that watches how you’re actually doing — damage taken, time to clear, health at the end of a wave, near-deaths — and steers the challenge toward a target band, paired with a procedural composer that spends a threat budget on a fresh, randomized roster every wave. Fixed tables can’t even reach the deep end of a long run; they’d just loop the early waves’ compositions against a capped curve and become trivial.
Then we corrected the correction. Players want to set a difficulty — taking that away entirely feels worse, not better. So difficulty modes came back, from Easy to Legendary, but reframed: not a multiplier table, just a bias that tugs the director’s target band one way or the other. You still choose; the game still auto-tunes within your choice. Loot scales with the difficulty you actually achieve rather than the tier you selected, so playing well makes the director ramp, which makes the rewards better. A later round pulled the marathon length back sharply, because a powerup card amplifies a weapon and has a stack cap, which means even a deep loadout only yields a finite number of meaningful picks — so the run length has to fit inside the rewards that exist, not the rewards we wish existed.
And then we didn’t build it. The phase is parked, deliberately. The honest engineering reason is that the first step — replacing the hardcoded wave count — is entangled with the enemy-scaling model, which lives in the exact part of the design that was still being actively redesigned. Building a large core-loop refactor against a moving specification, unsupervised, is how you ship a mess. So the day’s autonomous work steered toward additive, testable, new-file features and left the load-bearing refactor for when the design settles and a human can watch it run. This also answers an old complaint our own playtesting tooling has logged for months — that challenge tends to whipsaw between trivial waves and deadly spikes. The adaptive director is the structural fix for that, which is exactly why it’s worth getting right rather than fast.
Two Fixes That Restored the Feel
Buried among the features were two fixes that mattered more than they look, because both restored something the game had quietly lost. Leveling up, it turned out, had become silent: an old refactor disabled the celebration and a later leveling rework never switched it back on, so a core reward beat had been dead for dozens of versions without anyone tracing it. The fix re-fires the on-screen celebration — the golden aura, the banner — and adds a persistent pulsing pip beside the level number so the reward stays visible after the banner fades. The gotcha we rediscovered along the way is worth flagging for next time: the old message overlay is commented out of the page entirely, so every in-game announcement now has to be drawn on the canvas, and anything still trying to use the dead path is simply invisible.
The second fix concerns healing. Banking surplus healing toward rebuilding a lost spare tank was supposed to work from any source, but only health orbs and passive regeneration actually did it — the field medic, lifesteal, and the vampiric-rounds passive all clamped to maximum health and silently discarded the overflow. So healing at full health “did nothing,” inconsistently, depending on where the healing came from. The fix routes all of it through a single canonical heal function that clamps and credits in one place, and surfaces the banked progress as a visible fill on the health bar. The principle is the same one that runs through the whole day: three heal paths meant three chances to forget the overflow rule, and one chokepoint means zero. We also retuned asteroid health into a wider band with a real spread across size tiers, because the field had become a monoculture of low-health rocks — readable, but boring.
What the Cleanest Meta Actually Means
Step back from the feature list and the day has a spine. The naming rename, the single registry, the keystone budget, the refusal to make passives into cards, the one collision radius, the canvas-text line in the font system, the unified firing rule, the single heal chokepoint, the parked difficulty system — every one of them is the same move. Faced with a fork between more cleverness now and fewer ways for the thing to rot later, we kept taking the second road.
That’s what the cleanest meta means. It isn’t the most powerful build or the flashiest system. It’s the set of decisions that leaves the game legible — where each system has one identity, one place it’s defined, one place it’s consumed, and no hidden interaction lying in wait to become the thing everyone exploits. Forty-six rule-rewriting passives is a lot of rope, and the whole day was really about tying it off so the game can’t hang itself with it.
Next up are the ten scripted bosses the new phase engine is waiting for, and, once the design settles, the adaptive-difficulty brain that turns a finite run into a fight that actually learns who’s flying.



Leave a Reply