On Sale: GamesAssetsToolsTabletopComics
Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
Tags
(+1)

It's all C. Shockingly, the best approach was straightforward inverse-Z x horizontal distance, right in hblank. Initially it just added a reciprocal to a list of offsets, and while that was efficient enough to scroll every two scanlines instead of every four, it drifted like crazy. Correcting that drift created visible jumps. I tried a wide variety of clever nonsense, and none of it beat rock-solid frame-to-frame tracking.

And I do apologize for the sound in the credits.

There might be an update that lets NPCs wander up and down each plane. I got it working a few days before the deadline, but just barely, so it didn't make the cut. It requires triple-buffering. The hblank function does the math, as now, but writes the results to an array. That'd get used to place the sprites based on which row they're tracking. But sprites have a one-frame delay. So hblank needs to scroll based on the math it did two frames ago. That part worked annoyingly well. Moving things between rows was super janky, though, and I was dropping frames any time cool stuff happened. 

The mantra for this was clear: 60 Hz or die.

Well done then.
Doing nice fluid scrolling is not an easy task!
I wish you will be able to do what you want in the next updates.