Doug's Game Dev Log
About
2026-08-02

Banish It Before You Even Start

This is the post where td-survivors grows a spine of meta-progression: a between-runs shop where you spend coins on permanent upgrades, and a screen that lets you delete content from your own game before you ever press play. It's also the post where I, Doug, admit I've started fiddling with the actual art, because the placeholder squares were getting a little too comfortable. Two new enemy sprite sheets snuck in.

Last time I swore the series was done, right after I swore it was done the time before that. I contain multitudes and also I keep adding features. This one's about the stuff that happens outside a run.

The UNLOCK screen is a shop now

Every run, enemies you kill drop coins, and at the end you cash out: 3 bronze per wave you fully spawned. Coins carry like real change, ten bronze to a silver, ten silver to a gold, and they pile up between runs. The UNLOCK screen, which used to just hand out towers, is now where that money goes.

The new thing you can buy there is permanent upgrades: meta upgrades that are always active, in every run, forever, no card draw required. They go from level 1 to 100, and the level is the quantity you get. Each level costs 100 + level * 25 bronze, so they start cheap and turn into a genuine gold sink by the time you're deep in. Because the cost is bronze-granular, I had to teach the wallet to spend below the gold denomination, which is a sentence that means "I wrote spendBronze and a pile of tests for it and felt very responsible."

Wait, where did Banish and Reroll go?

If you read the cards post, you'll remember Banish and Reroll used to be cards: meta cards you'd luck into mid-run that let you throw back an offer or delete something from the pool. I've evicted both of them from the deck. They are no longer things you find. They are things you own.

Banish and Reroll are the first two permanent upgrades. Buy Banish to level 5 and every run starts with five banishes in your pocket. Buy Reroll to level 3 and every level-up comes with three "no thanks, deal again" tokens. Moving them out of the card pool did two nice things at once: it stopped the deck from wasting a slot offering you a reroll you didn't want, and it turned "I wish I could get rid of that card" from a lucky draw into a plan you make at the shop.

And they don't just work on level-up cards anymore. The tower-pick overlay, the screen where you choose which tower to build, now has the same banish and reroll buttons. Hate being offered the Cursed Idol every single time? Reroll the tower options, or banish it for the rest of the run. Same shared banishMode, same buttons, wired into both overlays instead of just one. (Banishing a tower rolls itself back if it would empty the pool, because a run with zero buildable towers is not a run, it's a screensaver.)

The part that broke my brain a little: permanent banish

Here's the feature I keep grinning about. On the UNLOCK screen, every tower card and every upgrade card now has a little red BANISH checkbox. Check it, the card gets an angry red border, and that tower or upgrade is gone from every future run's pool. Not this run. Every run. You are reaching into your own game and deleting content you don't like, permanently, before a single enemy has spawned.

It sounds unhinged and it's actually the best kind of player expression. Decided the Magnet Pylon is boring? Banish it forever and never be offered it again. Tired of one particular upgrade cluttering your draws? Gone. The pool is yours to prune.

There's exactly one rule keeping it honest: each permanent banish spends one from your per-run banish budget. So if you've bought Banish to level 5 and you permanently banish 3 things on the UNLOCK screen, you start each run with 5 - 3 = 2 in-run banishes left. The number of permanent banishes is capped at your Banish level, so you can't delete more than you've paid for; once you hit the cap, the unchecked boxes go disabled and politely refuse you. It's all persisted in the save file (banishedTowers / banishedUpgrades, backfilled onto old saves so nobody's progress explodes), behind pure, TDD'd helpers, because touching the save format without tests is how you turn a devlog into a support ticket.

The co-op asterisk, which is very funny to me

Remember the co-op server is a headless Node process that is the single source of truth? It has one glorious blind spot: it cannot read your save file. Your banishes, your rerolls, your carefully pruned pool, all of that lives in your browser's local storage, and the authoritative server has never met your browser's local storage and never will.

So in co-op, everyone starts with zero banishes and zero rerolls, exactly like a fresh save. All that meta-progression you grinded? The server shrugs. Whatever you deleted forever is back. It's a real limitation and I'm not going to pretend it isn't, but there's something poetic about a game mode where the server enforces radical equality by simply refusing to acknowledge that any of you have ever played before.

And yes, I finally touched the art

Confession time. For eleven posts the enemies have been Kenney's CC0 tiles, and they've served honorably. But I've started experimenting with actual sprites, and two of them landed.

Normie, the basic walker, got downscaled to a proper 64px sheet: a 256x256 texture laid out as a 4x4 grid of 64px cells, animating at 8fps. Smaller, cleaner, and it actually reads as a little blob wobbling along instead of a smear. Downscaling him also let me rebalance stage 1's wave schedule and drop the velocity ramp back to a flat 1.0, because he was, frankly, too chonky and too fast at the old size.

Speedy got the bigger promotion: his very own directional sprite sheet. Before, speedy was a single static tile that slid around like a hockey puck. Now he's got the same 4x4, 64px-cell layout as normie, so he animates directionally, actually facing where he's running. Wiring it up was almost anticlimactic: drop speedy.png in as a third texture, add an ENEMY_SHEETS.speedy entry, set sheet: "speedy" on the enemy, done. The renderer already knew how to animate a directional sheet from normie, so speedy just inherited the whole system for free. (There's some spare normie and a dog, "catioro", waiting in the wings for their turn. The bench is getting deep.)

I'm not claiming any of this is good art yet. It's me, a programmer, poking at a sprite sheet at midnight. But it's the first time the game has looked even slightly like it was made on purpose, and after a year of colored rectangles that feels enormous.

And here's the accidental art direction I've decided to just... embrace. The new sprites came out looking like viruses and bacteria: little round blobs. Instead of fighting it, I gave them happy, cute little faces, and that settled the whole tone. This is not going to be a serious game. It's a goofy one. You're defending against a swarm of smiling germs, and I'm leaning all the way into the silliness rather than pretending td-survivors was ever going to be grim and epic. It was always going to be dumb fun. Now it looks like dumb fun.

So what does a run look like now?

You show up at the UNLOCK screen with a fistful of bronze. You buy a few permanent upgrade levels. You permanently banish the two towers you've decided you hate, spending two of your banish budget to do it. Then you start a run, already holding rerolls and a couple of banishes, playing out of a deck you personally curated, watching a slightly-less-embarrassing normie wobble toward your towers, grinning the whole way. The run isn't just where you make choices anymore. It's where you cash in choices you made before it started.

Next time: I still don't know what the towers should be. If the enemies are cheerful little microbes, what am I building to zap them? White blood cells? Hand-sanitizer turrets? Tiny furious doctors? I genuinely have no idea, so this is an open call: if you've got a good idea for the towers, mail it to dougneves@gmail.com. The best pitch might just end up in the game. See you when it looks even more like a game, and a lot less serious.