Tuesday, October 10, 2017

Knuckles in Sonic 2: control quirks

In Knuckles in Sonic 2, if you perform the inputs for a spindash while Knuckles is sliding on the floor after landing from gliding, Knuckles will simply jump out of the sliding pose, completely ignoring the down input:


This is quite annoying because in Sonic 3 & Knuckles, doing the same inputs successfully initiates a spin dash directly from the sliding pose, without having to wait for Knuckles to get back up. This is due to a feature I'll call slow duck:


Here's the code responsible for making the player duck into a roll when they press the down button, as seen in Sonic 3:
Player_Roll:
    tst.b   status_secondary(a0)
    bmi.s   locret_127D0
    move.w  ground_vel(a0),d0
    bpl.s   loc_127B8
    neg.w   d0

loc_127B8:
    cmpi.w  #$80,d0
    blo.s   locret_127D0
    move.b  (Ctrl_1_logical).w,d0
    andi.b  #button_left_mask|button_right_mask,d0
    bne.s   locret_127D0
    btst    #button_down,(Ctrl_1_logical).w
    bne.s   Player_ChkRoll

locret_127D0:
    rts
The breakdown, as usual:
  • First, we check the high bit of the player's status_secondary bitfield. If it's set, do nothing.
  • Next, take the player's ground velocity and calculate its absolute value. If the player is traveling at a speed lower than 0.5 pixels per frame, do nothing.
  • Next, check if the player is pressing either the left or right buttons. If they are, do nothing.
  • Finally, check if the player is pressing the down button. If they are, branch to Player_ChkRoll, which will put the player in their rolling pose and play a sound effect, only if they weren't already rolling.

Now, here's the same function, as seen in Sonic & Knuckles:
SonicKnux_Roll:
    tst.b   status_secondary(a0)
    bmi.s   locret_1177E
    move.b  (Ctrl_1_logical).w,d0
    andi.b  #button_left_mask|button_right_mask,d0  ; is left/right being pressed?
    bne.s   locret_1177E                            ; if yes, branch
    btst    #button_down,(Ctrl_1_logical).w         ; is down being pressed?
    beq.s   Player_ChkWalk                          ; if not, branch
    move.w  ground_vel(a0),d0
    bpl.s   loc_1176A
    neg.w   d0

loc_1176A:
    cmpi.w  #$100,d0                                ; is Sonic moving at $100 speed or faster?
    bhs.s   Player_ChkRoll                          ; if so, branch
    btst    #Status_OnObj,status(a0)
    bne.s   locret_1177E
    move.b  #8,anim(a0)                             ; enter ducking animation

locret_1177E:
    rts
So, what's changed? Here's the breakdown:
  • First, all the button checks have been moved up to the start of the code. The player's speed is only checked when the player presses the down button without also pressing either the left or right buttons.
  • Next, if the player is traveling at a speed higher or equal to 1.0 pixels per frame, branch to Player_ChkRoll, which will put the player in their rolling pose if they weren't already rolling.
  • Finally, check whether the player is standing on an object. If they are, do nothing. Otherwise, put the player in their ducking pose.


And that's the slow duck: a convenience that allows the player to perform a spindash without first coming to a complete stop, which in turn allows Knuckles to spindash directly out of a glide.

Do you see why the slow duck isn't in Knuckles in Sonic 2? At some point during development of Sonic & Knuckles, the code for the Knuckles object was copied over and adapted for Knuckles in Sonic 2. Later, when slow duck got added to Sonic & Knuckles, the Sonic 2 copy didn't receive the update. Once again, Knuckles is a snapshot of days gone by.

Going through all the Sonic & Knuckles prototypes we currently have, we find that the slow duck is present in every last one, all the way back to the 0408 prototype, so the Knuckles object had already been replicated by then. Unfortunately, there's no way to know exactly when this particular feature got added to the game.


There's another quirk about the Knuckles object in Sonic 2 that we can accurately date, though. In Sonic & Knuckles, if the player stops moving while climbing a wall, Knuckles will reset to a specific frame of his climbing animation. In Sonic 2 however, he just remains in whatever frame was being displayed at the time.


Going through the currently available prototypes, we find the Sonic 2 behavior is present all the way up to and including the 0525 prototype, whereas the final Sonic & Knuckles behavior appears starting from the 0606 prototype. This means the feature was introduced at some point in the intervening two weeks.

5 comments:

  1. Have you also noticed the HUD in Knuckles in Sonic 2?

    Do you know what code handles jumping after rolling and the associated control lock?

    ReplyDelete
    Replies
    1. I also know that Knuckles in Sonic 2 lacks Knuckles-specific sound effects and that rolling behavior on hills and as Super Sonic is different between Sonic 3 and Sonic & Knuckles.

      Delete
    2. Right, Knuckles is silent because the game uses the Sonic 2 audio driver, and Sonic 2 doesn't have those sounds.

      The audio stuff isn't my strong suit though, which is why I avoid bringing it up.

      Delete
  2. Ever noticed how Knuckles' fists seem to move a bit when gliding in Sonic 2?

    ReplyDelete
    Replies
    1. I know exactly what you're talking about, but I'm not sure I'm ready to discuss optical illusory phenomena on this blog!

      Delete