Lab Journal
VirusMon: bedrooms, ledges, and a whole new town

VirusMon: bedrooms, ledges, and a whole new town

lab-journalvirusmon

One of those Saturdays where the project actually starts looking like a game instead of a tech demo. Spent the day on VirusMon pushing through the story intro, redesigning the north road (twice), and standing up a proper second town.

Story intro sequence

Started the day by writing the story bible and intro-sequence spec, then an implementation plan, then actually shipping it. The shape of it:

  • Schema v4 with storyStage accessors so the world knows where each player is in the opening beats.
  • New players now spawn starter-less in a bedroom, with encounters guarded until they actually have a virus. No more "wander into grass with nothing and immediately die" situation.
  • Added generic kind-tagged trigger map objects so I can drop interaction points into Tiled without bespoke code per trigger. The PC in the bedroom uses one to fade into the cyber bedroom (storyStage 1), and the lab robot uses one to hand over the first virus (storyStage 2).
  • Per-player instanced zones via an instanceKey room filter — this is the bit that makes the bedroom feel like your bedroom and not a shared MMO closet.

Also fixed a small but annoying signup wizard bug where the HTML step order didn't match the JS — LOOK was rendering before NAME the way the code expected, but the markup had them swapped. Classic.

Added a "you come to" popup when arriving in the cyber bedroom, and then immediately had to fix it because it was firing on every house visit instead of just the PC-wake transition. One-shot guard, done.

Bedrooms as actual rooms

The bedrooms started as placeholder rectangles. By end of day they're real spaces:

  • Re-tiled as proper top-down rooms with only the back wall visible (the Gen 1/2 convention). Felt obvious in retrospect — full four-wall enclosures look wrong at this camera angle.
  • Dedicated classic bed + desk-computer sprites for the normal bedroom, and the cyber variants for the cyber bedroom.
  • The cyan house in town is now the player's house, which flows into the cyber bedroom on entry. The geography finally has narrative meaning.
  • Fixed a bed clipping issue and dropped in source art for floors/walls/windows for a later pass.

One small camera tweak that paid off: the zoomBounds clamp now multiplies the whole-map fit by 0.88 so small rooms get a bit of breathing room instead of being pinned edge-to-edge. Tiny change, much nicer feel.

Route-2, take one: cyber tree-maze

First pass at the north road was a cyber-style tree-maze with forced tall grass. Sliced four extra cyber tree variants into the atlas to get enough visual variety for the maze walls. It worked, it looked moody, and then I looked at it for a while and decided it wasn't the right vibe for the second route in the game. Too dense, too punishing.

Route-2, take two: Route 1 recreation with ledges

Pivoted to rebuilding route-2 as essentially Gen 1's Route 1 — open route, fences, one-way ledges, cobblestone path. That meant:

  • Slicing Gen-2 ledge and fence tiles into the cyber atlas.
  • A MapBuilder ledges layer with dynamic-id toTiled.
  • One-way ledge movement on the server — the actual mechanic, not just the visual.

The resulting design forces you through tall grass going up and lets you road-hop down via ledges, which gives the route a real directional grammar: going north is the "adventure" direction, going south is the fast travel home. Filled the open chambers with tree forests and tidied the choke edges to remove grass slivers.

Town-2, the northern town

With route-2 leading somewhere, it needed to lead somewhere. Built town-2 as a Viridian-style zone:

  • Sliced northern-town buildings (gym, hospital, virus-market, houses, hall) from a new art drop.
  • Placed buildings on grass with a central fenced tall-grass garden as a focal point.
  • Added signs by the mart and hospital, removed an awkward mid-road sign.

The fact that I had the slice_town.py tooling and more_buildings.png source art ready meant going from "I need a new town" to "there's a new town wired to route-2" took a single afternoon block.

Earlier carryover: game client layout

Also closed out the game-client-layout work from the previous session. The spec had been written in a worktree that got cleaned up before committing, so I had to recover it from the prior session's transcript before I could even start planning implementation. Lesson: commit specs before nuking worktrees. The actual implementation — flex shell, 320px identity sidebar, Scale.RESIZE, layoutCamera() with fit-clamped wheel zoom, battle/roster as centered panels over the paused zone — went through cleanly with two-stage reviews per task. Also caught and fixed a 4px inline-baseline gap under the canvas from the default vertical-align, which is the kind of thing that haunts you for weeks if you don't track it down.


Good day. The game has a story opening, a real second route with a real mechanic, and a second town to walk into. Next session is probably going to be filling town-2 with actual NPCs and making the virus market do something.