Thursday, September 21, 2017

Solid object collisions

There are two kinds of collisions that can be registered between the player and other objects, which we might call solid collision and responsive collision. As I've previously mentioned, an object can obtain solid collision by calling a function such as SolidObjectFull.

A couple of important things happen when the player touches the top of one of these objects. First, the object sets bit 3 of the status bitfield, at offset $2A of the player's SST. This flag signals the player object that it's presently standing on top of an object, so it should skip over the code that checks the level blocks at the player's feet and determines whether the player should be falling or not.

The next thing the object does is copy the address of its own SST to offset $42 in the player's SST. This is done so the player object can later consult the state of the object it's standing on and react accordingly. In practice, this is only used to look up the object's x_pos and width_pixels values, to determine whether the player is close enough to the edge of the object that one of the teetering animations should play.

Lastly, the object also sets bit 3 or 4 of its own status bitfield, depending on which player is standing on it. This is sort of redundant, because the two player SSTs are both always at the same RAM address, meaning the object could just look up the previous two offsets to obtain the same information, but there you go.

It's important to note that the player object puts no effort into ever clearing its own "standing on object" flag: it's the solid object's responsibility to keep calling the SolidObjectFull function, check whether the players are still there, and if not, clear their "standing on object" flags depending on the value of its status bitfield. Breakable objects should take care to also clear the flags when they're destroyed.

Armed with this knowledge, you should be able to understand why the "slope glitch" behaves as it does.


Due to an oversight in the object's code, when Tails breaks the ice block, Sonic's "standing on object" flag isn't cleared. The code that checks the level blocks at his feet continues to be skipped, causing him to float, and since the block has been destroyed, it will never detect Sonic running off the edge, and so he'll stay up there until he jumps, which sets his "airborne" flag.

When he lands on the ground, Sonic is affected by the floor's angle for a single frame. Afterwards, his "airborne" flag is once again cleared, whereas his "standing on object" flag is still set, so the code that checks the level blocks at his feet gets skipped again, making him float once more.

Because the block's SST got zeroed out when it was destroyed, its x_pos and width_pixels report an infinitely narrow object whose center is all the way at the start of the level, activating the teetering animation.

The only way out of this mess is to jump on a different object, and then either run or jump off of that one. If nothing else goes wrong, the second object will clear the "standing on object" flag properly and disable the glitch.

4 comments:

  1. 1) Can Sonic break Tails's gravity?
    2) How did Sonic 3 Complete correct this?

    ReplyDelete
    Replies
    1. 1) Surprisingly, no. The object is programmed to clear Tails' flag, as well as the flag of whoever broke the ice block.
      2) By clearing the flag of everyone who was actually standing on the block, I assume.

      Delete
    2. I think Sonic can break Tails's gravity in Sonic 3 alone.

      Delete
    3. Can confirm, just tested this. Here's a screenshot:

      https://i.imgur.com/vgfsBUM.png

      Delete