Beginning the work on v2, rethinking positions
All Super Tilt Bro. cartridges are now shipped. It is time to begin to work on the second version. It all begins with in-depth refactoring. Let's fix version 1's shortcomings before making a better game. We will begin by changing the way we handle positions.
The NES generates 256x240 pictures. Nice! We can describe any on-screen position with two bytes: one 8-bits unsigned integer for the horizontal component and another for the vertical component. In Super Tilt Bro. v1, if you go out of screen, you die. Technically, you will always be on screen, so this simple "one byte per component" system is enough.
Some objects, like characters, need more flexibility. In this case, we can add a second byte, the sub-pixel position. It becomes a fixed point number, allowing to have finer-grained positions for this object. It is especially useful when it comes to movement speed, we can easily move such an object by 1.5 pixels per frame.
This system works well, but has two shortcomings.
The first is technical, and we can live with it: signed and unsigned integers don't mix well. Indeed, when we have two on-screen points, subtracting one by another and you get a vector... At least that's what my math teachers told me. Actually, with this system, we subtract two unsigned integers. It is flawless while the result is positive. When the result is negative, since we work with unsigned numbers, we overflow. There is always a path to work with it, but sometimes it is a pain.
The second problem has no workaround, Super Tilt Bro. v1 was released with it: allowing the character to go slightly off-screen before dying makes the game more pleasant. With this positioning system everywhere in the game (characters, hitboxes, platforms, particles,...), we cannot simply implement the concept of "out of screen" without reworking a good part of the engine. Super Tilt Bro. v1 just does not understand the idea of "out of screen". By the way, in its logic, we do not die "when we go out of screen" (it is meaningless), but "when we are moving to the left and finish on the right of the screen".
To solve these shortcomings, the positioning system is rethought. Instead of storing a component in an unsigned byte, a two-bytes signed integer is used. The most significant byte is the screen byte, the least significant one is the pixel byte. Of course, objects needing a fine-grained position can add a sub-pixel byte.
This new system avoids mixing signed and unsigned integers and opens the way to let characters go off-screen. That's nice. Moreover, we have lots of space. One byte for the screen, there is 256 possible screens. If, one day, we want to add an adventure mode based on scrolling, it would be feasible.
This change comes at a cost. Storing positions requires more RAM while computing it puts more load on the CPU. Happily for CPU budget, there was a big optimization done while refactoring animations. It is much more impacting than some 16 bits additions.
Most of it was done during a mini marathon. While I was doing this marathon, I posted my daily progress on Twitter. I hope you like this kind of reports. I will surely do it again, I loved it.