Inspiration

It started with the oldest standoff in any household: "clean your room." I wanted to flip that chore into a power fantasy — what if tidying up were the enemy, and staying messy was how you won? Tower defense is a genre I love, but I were tired of grim sci-fi and fantasy skins on the same formula. I wanted something cozy, funny, and wholesome, where the "threat" is a parade of soft stuffed animals and the worst thing that can happen to you is your floor gets clean.

What it does

Messy Bedroom is a mobile tower defense with the polarity inverted. You're a kid refusing to clean up, and your toys are trying to put themselves away without you. Each level is a short Build → Defend cycle:

  • Build: gather blocks from a single shared pile scattered across the floor, and stack them into towers. A tower's colour decides its attack type, and its height decides its range:

$$ R = R_0 + k\,h $$

where \(h\) is stack height. Build a tower in one colour for a synergy bonus, or mix colours for broader coverage at the cost of that bonus.

  • Defend: toys wake up and march blocks toward the toy box, raising a Tidiness Meter. Towers fire automatically, but a tower that takes enough damage sheds its own blocks back onto the floor — the same pool either side can reclaim. You don't win by defeating every toy; you win by stalling: keep tidiness below the pass line until the level's day-timer runs out. Because it's a threshold, players can trade a small leak on one flank for a stronger hold on another.

  • Levels pay out an in-game allowance, weighted toward messier finishes, spent in an upgrade shop between rooms:

$$ \text{Allowance} = A_{\max}\left(1 - \frac{T_{\text{final}}}{T_{\max}}\right) $$

The prototype ships four levels with real unlock gating (each level opens by winning the one before it), two tower colours (RED Blasters and BLUE Freezers), five enemy tiers, and a full result screen with star ratings and payout. It's a self-contained, offline-capable portrait build — no network access at runtime, no external assets.

How I built it

Everything is TypeScript, Three.js (r185), and Vite, rendered as 2.5D orthographic scenes built entirely from Three.js primitives — no rigged models, no GLTF. That constraint kept the offline package small and the whole thing legible on a phone screen.

Under the hood, the codebase is split into four strictly separated layers: Config (pure data), Sim (pure game logic with zero Three.js imports), View (reads sim state, never mutates it), and Input/UI (enqueues intents the sim consumes on its next tick). That separation is what made the project survive many sessions of iteration without the logic and the rendering slowly fusing into an unmaintainable mess.

Design work happened before a line of gameplay code: a living design bible fed a full Game Design Document, a first-fifteen-minutes Player Journey Map, a Visual Concept Package (Midjourney-generated, locked to one style reference for cohesion), and a riskiest-first Production Plan.

The actual implementation was almost entirely prompt-built: I worked with Claude through small, tightly scoped prompts, one verifiable pass at a time, with every pass checked in a real browser — dev console open — before moving to the next. A running build log tracked every locked decision and every session's work, both as working memory across sessions and as a required competition artifact.

But the design work was done mostly by my. I had Claude create a level editor with drag and drop functionality. This was both for the level design/layout, and also for the enemy wave scheduling. Claude built a drag and drop timeline for that part.

Challenges I ran into

A few fragile spots came up more than once and taught us to watch for them:

  • RNG-stream fragility. Reweighting enemy spawn probabilities non-monotonically silently reshuffled every seeded test that depended on spawn order — a reminder that "just a balance tweak" can quietly break determinism.
  • Block-conservation invariants. Our shared block economy tracks every block's state explicitly, and more than once a missed reset path left "orphaned" claims behind. I ended up auditing every reset path, not just the obvious ones.
  • The missing-call-site pattern. New tower functions kept a trailing modifiers parameter that was silently omitted at real call sites — a class of bug that only shows up by checking every caller, not just the function definition.
  • Packaging for a fully offline submission. Three.js r185 splits into three.module.js and three.core.js, and missing either one silently breaks the vendor bundle. I also learned the hard way that our own offline-verification tooling had a regex bounded at 400 characters that gave a false PASS on a 3,500+ character import line — a bug in the safety net itself.

Accomplishments that we're proud of

We're proud that the submission is genuinely, verifiably offline: I unzipped a clean copy of the build, served it from a local server, opened it in a private browser window, turned the internet off entirely, and played a full session end to end — first run through a 3-star win, level unlock, a shop purchase, and settings' clear-data flow — with zero console errors and zero external network requests. We're also proud of catching and fixing two separate packaging bugs (a tar-file mislabeled as a zip, and that stale verification regex) before either one became a disqualifying surprise at submission time.

What I learned

The biggest lesson was to keep returning to one question — is the core loop itself fun — before adding anything else, and to treat "the AI says it's done" as a claim to verify, not a fact, every single time. Readability turned out to be a real design constraint, not decoration: colour-as-signal is what keeps a busy floor of blocks and toys parseable on a small screen. And keeping simulation logic completely free of rendering code paid for itself many times over — it's the reason a four-layer architecture built early could still absorb a wave system, an economy, and a shop late without cracking.

What's next for Messy Bedroom Prototype

The full design calls for three more tower colours (Yellow Zappers, Green Goo, Purple Piercers), a Sugar Meter powering active kid-abilities, additional mess zones beyond the four shipped here, a day/night cycle that reshapes each room's mood and pressure, and mid-defense path-shaping. With the completion grant, the next step is rebuilding Messy Bedroom on Meta Horizon's early access creation tools — including the game's signature idea I haven't gotten to yet: your own Meta Horizon avatar, dropped into the fiction as the doll, physically scrambling across the floor to reclaim blocks and repair towers in real time.

Share this project:

Updates