Dev blog

The 24 px grid

For about a week the game ran on a 16 px logic grid under 24 px art, and as of this evening the logic grid is 24 px too.

Movement, collision, warps, NPCs and events have sat on a 16 px logic grid since the field engine went in on day one. The tile art I picked last week, the WinLu packs, is drawn on 24 px tiles, so three logic cells make two art tiles. A wall edge in the picture often fell halfway through a cell. The packs are made for RPG Maker MV, where one art tile is one walk cell, so our grid fought their design. The map format doc I approved on the 20th described the two grids and recommended keeping 16 px for the logic. I approved every point in it.

What it cost

The cost showed up in the World Editor. It had two grid toggles and an 8 px snap for objects that fit neither grid, and a map could only change size in steps of three cells. The bar counter is 72 px wide, which is 4.5 cells, so its footprint got rounded up to 5.

The decision

Yesterday Claude scoped five options: keep two grids and hide the 16 px one in the editor, move the logic to 24 px, move it to 8, shrink the art to 16, or change the resolution. It recommended 24 and was straight about the cost, about the size of the 640x360 move, with roughly 300 code sites, 16 map files and a new save format. I chose that one.

Then Claude ran a spike. It converted the bar and Lantern Row with a script and three hand fixes each, and I played both next to main. My verdict was “definitely WITHOUT the flag feels much better, let’s go with that. everything else looks good”. The flag kept the old step timing, which made each step 1.5 times as far. Without it you walk at the speed you had.

That evening Claude wrote the design for the full move, nine work packages with the pass lines written before any code, and I approved it with “let’s kick this off”. Eight open pull requests had to merge first because they touched the same maps and editor files, and I agreed to stop painting maps until the move merged.

Overnight

Claude built it overnight and through today, package by package, and a runner and a reader that did not write the code checked each one. The flip itself, package 3, failed its first round with two Important findings and passed the second at 8.5. By 4 this morning the first five packages were done, and Claude had started the save format. A save holds positions in cells, so an old save moves cell by cell and the old text stays under a backup key.

Two things changed that you can feel. Walking keeps its speed in pixels per second, so a step is 18 frames where it was 12, and dash is about 4.5 percent slower because steps are whole frames. Random encounters are scaled to the bigger cell, so the same distance gives the same fights.

Lantern Row at night in the rain on the 16 px grid, with the Last Rites, Drowned Saint and Sleeptube signs and two stalls under string lights

The same street on the 24 px grid, with the camera a little further along: the Drowned Saint, Sleeptube and Kowloon Threads signs above the street and the two stalls below

What the verifiers missed

Package 3 had passed at 8.5 and I still found six crops that looked wrong. A counter in the shops is two or three pictures side by side. Moving a person onto the new grid had put some of them behind a counter picture, and the fix nudged the counter, but one picture at a time. So the hotel counter’s right half sat 7 px higher than its left. In the annex the chevron under the two doors had slid 12 px to the right of them, because a prop that grows with the cell kept its left edge instead of its center. The check that would have caught the counters, comparing touching pictures before and after, did not exist yet.

A crop of the hotel counter, the 16 px version on the left and the 24 px version on the right, where the right half of the counter sits higher than the left half

A crop of the annex floor, the 16 px version on the left and the 24 px version on the right, where the chevron below the two doors sits to the right of their center

Claude fixed the converter, and no piece had to be nudged by hand in the editor. A counter now moves as a whole run and a prop that changes size keeps its center, each with a test that fails without the fix. I merged PR #231 a little after 6.

All 16 maps are on the 24 px grid, the World Editor has one grid and a one-cell resize step, and 4,317 unit tests pass. A few end-to-end specs fail here and on main alike. The barkeep’s spot, the skewer stall’s spot and the people who now stand 8 to 16 px lower are still mine to fix in the editor, and map painting is open again.