Wednesday, December 27, 2017

Roll height bugs, part 1

The size of a player's hitbox is determined by the values at offsets $1E and $1F of their SST, respectively known as the y_radius and x_radius attributes in the current disassembly:
y_radius =              $1E ; byte ; collision height / 2
x_radius =              $1F ; byte ; collision width / 2
As their labels imply, these attributes denote the player's radius in pixels across the vertical and horizontal axes, and as such, their values must first be doubled in order to obtain the actual collision size. Furthermore, since a radius of 0 isn't particularly helpful, the values stored in these attributes are actually off by a single pixel, so therefore we must also add 1 to each value before doubling it.

For instance, the Sonic object is initialized with a y_radius of $13 and an x_radius of 9. These values are off by one, so the true radii are 10 for the horizontal radius and $14, or 20 for the vertical one. Doubling these values gives us Sonic's final collision size of 20×40 pixels.


When Sonic curls into a ball, his hitbox gets reduced to the adequately smaller size of 16×30 pixels. However, since the precise location of the hitbox's edges is determined from Sonic's X and Y coordinates, which in turn define the center of the object, the game must also make sure to move Sonic down by five pixels in order to keep him grounded:


As one might expect, this easily lends itself to lots of tiny oversights. For example, when a player jumps directly out of a roll, the larger hitbox is incorrectly applied, causing them to hit the ceiling sooner than intended.

In Sonic 2, this also caused the player to suddenly jolt up after landing, thanks to the game subtracting five pixels from their Y position in order to prevent their hitbox from digging into the floor when it expands back to its normal size (which has no effect due to the previous bug).


These changes to the player's position also take their toll on the camera. Because Sonic suddenly moves down by five pixels when he curls into a ball, the camera counteracts this by aiming itself five pixels above his actual position so as to prevent the entire screen from jerking down awkwardly. However, this code does not account for Tails' shorter hitbox, and so whenever Tails curls into a ball, the screen awkwardly jerks up instead:


Over the next couple of posts, I'll talk about some of the more interesting height-related bugs. Not all of them; there are far too many to count.

2 comments:

  1. So why does it use a radius if it causes problems? Is it just for easier calculation with Sonic's coordinates pointing to his centre?

    ReplyDelete
    Replies
    1. I have no clue, really. There might be a really good reason why they went with a center + radius approach, but it may also just be an early design decision that later came back to bite them in the ass.

      Delete