From Sonic Retro

Sonic Physics Guide


  • The research applies to all four of the Sega Mega Drive games and Sonic CD.
  • The following describes physics that only apply when the Player has no special power-up and is not Underwater.
  • General airborne physics is detailed in Air State.


 jump_force: 6.5  (6 for knuckles)
 gravity_force: 0.21875

Jump Velocity

Jumping is affected by the angle the Player is at when they do it. It can't simply set Y Speed to negative jump_force - they need to jump away from the Ground Angle they're standing on. Instead, both X Speed and Y Speed must have jump_force subtracted from them, using cos() and sin() to get the right values.

More pseudo-code:

 X Speed -= jump_force * sin(Ground Angle)
 Y Speed -= jump_force * cos(Ground Angle)

Notice how the jump values are subtracted from the X Speed and Y Speed. This means their speeds on the ground are preserved, meaning running up fast on a steep hill and jumping gives you the jump speeds and the speeds you had on the hill, resulting in a very high jump.

Variable Jump Height

Though we've become accustomed to it now, at the time Sonic the Hedgehog was first released, there were a whole lot of games that had fixed jump heights. No matter how quickly you released the jump button, the character would sail up into the air the same number of pixels. Games like Mario and Sonic were some of the first to have more variable and responsive controls, allowing for an improved sense of control over the character, and therefore a much more fun - and forgiving - gameplay experience.

So how does variable jump height work?

If the jump button is no longer being held, and you are currently jumping (in the air after pressing jump, not walking or rolling off the ground or pushed away by a spring etc), the computer checks to see if Y Speed is less than -4 (e.g. -5 is "less" than -4). If it is, then Y Speed is set to -4. In this way, you can cut your jump short at any time, just by releasing the jump button. If you release the button in the very next step after jumping, the Player makes the shortest possible jump. This happens whenever you aren't holding the jump button and are currently jumping, not just on the release of the button.

The check to see if the button is not being held is performed before the Player is moved to his new position and gravity_force is added to Y Speed.

Bugs when Jumping

Because the Player is moving from one action to another, at the same time as changing his collision sensor arrangement, and at the same time as changing speed and leaving the floor... some bugs can occur when launching from the ground and when landing.

Disturbingly, the game checks to see if you press the jump button before moving the Player. If you do press the jump button, it exits the rest of the cycle - so the Player doesn't move at all during the step in which you jump, vertically or horizontally.


This can mean that in the next step it can detect a release of the jump button and the Player will move up at a Y Speed of -4 without having ever moved up at the speed of jump_force.

As described in Sensors the Player's sensor arrangement will change in size depending on what they're doing. When rolling/jumping, this arrangement becomes smaller. Whenever this happens, the Player will move up or down by 5px to keep his bottom most pixel in the same position. However when you are rolling and perform a jump, the Player's collision size incorrectly becomes it's standing size rather than the smaller rolling size. This in turn causes a few bizarre issues.

Since while jumping the Player is in his ball form, they will still 'uncurl' when they land, and this involves setting the Width and Height Radius to standing height and subtracting 5 from Y Position. This of course will simply move the Player's bottom most pixel up by 5 if their sizes don't change size. So, when the Player lands from this jump, it just assumes their Height Radius is becoming big again, so 5px is subtracted from his Y Position. However because their Size didn't change at all and the Player was already at floor level, they just rise 5px above the floor instantly upon landing.


This results in them making contact with the floor, then being moved up 5px then falling back down slowly via gravity.