Ok, THIS is where having an automatic vram buffer system that does updates during NMI really starts to become useful.
There are so many ppu updates in scrolling continuously, it helps to have an auto update system. You want to update on the opposite nametable that you are on so the user can’t see it change. And, only a little at a time (not too many to overload the system). Let’s look at it frame by frame as I’m scrolling to the right. I’m doing buffer_4_mt() twice per frame, which draws 8 blocks per frame.
So, I don’t want to do too many PPU updates in 1 frame, that’s why I break it up into 4 frames of updates.
Level design in Tiled.
So, I made 5 rooms worth of levels (easily expandable). Once you scroll right, it automatically updates just off the screen to the right, where you can see. It’s reading data from the collision map, like before, but I have to reload new maps as we move.
There are now 2 collision maps of 16×15 metatiles (240 bytes each). Every time you cross into another room, it loads the next collision map just off the screen to the right. We could have read directly from the ROM for collisions, but the advantage of having it in RAM means it is destructable / modifiable. Like when Mario breaks a block, or when Link (Zelda) pushes a block to the side.
I’m still making the rooms 1 room at a time (see the previous metatile page). The Tiled .csv files are processed with a py script into a c array. I import those to the code, and added an array of pointers to these arrays.
Note, if you expand this, you need to also change the max scroll constant.
I decided that 1 pixel per frame seemed a bit slow, so I modified all the movement and collision code to handle variable speeds bigger than 1 pixel, and also collision ejection bigger than 1 pixel. It seems to work ok now, but I didn’t test speeds over 2 pixels per frame.
And it also works across the room edges, which is the tricky part, but that complicates the math. When it checks 4 points, each of those points might be in a different room, so I accounted for that. The bg_collision() function is generalized, so it should work for enemy objects checking collisions too, when we add those later on.