Actions

Difference between revisions of "SPG:Jumping"

From Sonic Retro

(Simplifying and standardising object & character variables)
(Moved slope jumping to this guide, removed unnecessary inaccurate air drag calculations, Also replaced "Sonic" with "the Player")
Line 7: Line 7:
 
==Air Acceleration==
 
==Air Acceleration==
  
When Sonic is airborne, he can accelerate twice as fast as on land (''air'').
+
When the Player is airborne, they can accelerate twice as fast as on land (''air'').
  
There is no friction in the air (but there is a complicated drag effect that will be explained later), and pretty much, once Sonic has a certain X Speed in the air, he'll just keep going at that speed until you tell him otherwise or he hits a wall.
+
There is no friction in the air (but there is a complicated drag effect that will be explained later), and pretty much, once the Player has a certain X Speed in the air, they'll just keep going at that speed until you tell them otherwise or they hit a wall.
  
 
Furthermore, there is no distinction for deceleration in the air, either, so pressing {{left}} simply subtracts ''air'' from X Speed no matter what, and pressing {{right}} adds ''air'' to X Speed.
 
Furthermore, there is no distinction for deceleration in the air, either, so pressing {{left}} simply subtracts ''air'' from X Speed no matter what, and pressing {{right}} adds ''air'' to X Speed.
Line 17: Line 17:
 
==Gravity==
 
==Gravity==
  
Gravity ''grv'' is added to Y Speed in every step in which Sonic isn't on the ground.  It's what makes him fall downward when he runs off of cliffs.  It's also what stops him from moving upward forever when he jumps.
+
Gravity (''grv'') is added to Y Speed in every step in which the Player isn't on the ground.  It's what makes them fall downward when they run off of cliffs.  It's also what stops them from moving upward forever when they jump.
 
 
 
==Top Y Speed==
 
==Top Y Speed==
  
In Sonic 1, Sonic's Y Speed does not seem to be limited.  As he falls, ''grv'' continues to be added to Y Speed, increasing indefinitely.
+
In Sonic 1, the Player's Y Speed does not seem to be limited.  As they fall, ''grv'' continues to be added to Y Speed, increasing indefinitely.
  
In Sonic CD, however, a limit was introduced so that Y Speed does not exceed 16 pixels per step.  This limit is important so that Sonic never outruns the camera, or passes through solid ground because he's moving so fast per step that he never even collides with it.  I believe it was introduced in Sonic CD because of the increased height in the design of levels such as Collision Chaos, and the endless vertical shaft in Tidal Tempest.  Without the limit, Sonic would accelerate to ridiculous velocities in some of these areas and probably break the game.
+
In Sonic CD, however, a limit was introduced so that Y Speed does not exceed 16 pixels per step.  This limit is important so that the Player never outruns the camera, or passes through solid ground because they're moving so fast per step that they never even collide with it.  Most likely introduced in Sonic CD because of the increased height in the design of levels such as Collision Chaos, and the endless vertical shaft in Tidal Tempest.  Without the limit, the Player would accelerate to ridiculous velocities in some of these areas and probably break the game.
  
 
  <nowiki>
 
  <nowiki>
Line 32: Line 32:
 
==Air Drag==
 
==Air Drag==
  
Each step Sonic is in the air, a special formula is performed on Sonic's X Speed, but only if certain conditions are met.  First, Y Speed must be negative.  Second, Y Speed must be more than -4 (e.g. -3, or -3.5, is "more" than -4).  Third, absolute X Speed must be greater than 0.125.  If these conditions are true, X Speed is multiplied by a factor of 0.96875.
+
Each step the Player is in the air, a special formula is performed on their's X Speed, but only if certain conditions are met.  First, Y Speed must be negative.  Second, Y Speed must be more than -4 (e.g. -3, or -3.5, is "more" than -4).   
  
 
  <nowiki>
 
  <nowiki>
 
if (Y Speed < 0 && Y Speed > -4)
 
if (Y Speed < 0 && Y Speed > -4)
 
{
 
{
     if (absolute(X Speed) >= 0.125) X Speed = X Speed * 0.96875;
+
     X Speed -= ((X Speed div 0.125) / 256);
 
}
 
}
 
</nowiki>
 
</nowiki>
  
Actually, this is just an approximation, and I'll explain why.  Since the originals use 2 bytes for Sonic's speed value, where the first is pixels, and the second is sub-pixels, a speed of 6.5 pixels per step would be expressed with the hexadecimal value $0680.  In decimal, that would be 1664.  Clearly Sonic does not move over a thousand pixels per step!  1 pixel = $100 (256), half a pixel = $80 (128).  Air drag in the original game is therefore something more like this:
+
Air drag is calculated each step before ''grv'' is added to Y Speed.
  
<nowiki>
+
==Jump Velocity==
if (Y Speed < 0 && Y Speed > -$0400)
+
Jumping is affected by the angle the Player is at when they do it. It can't simply set Y Speed to negative ''jmp'' - they need to jump away from the Ground Angle they're standing on. Instead, both X Speed and Y Speed must have ''jmp'' subtracted from them, using cos() and sin() to get the right values.
{
 
    X Speed -= (X Speed div $0020); //"div" is division ignoring any remainder
 
}
 
</nowiki>
 
 
 
If we were to perform the same calculation on our comparatively lower X Speed values, which are always going to be lower than $20 (32), X Speed will be completely unaffected. Why?  Because any number lower than 32, when divided by 32, ignoring the remainder, results in 0. This is why the original game doesn't have to check if X Speed is higher than a certain value before bothering to calculate air drag - if X Speed is $001F or less, nothing will happen anyway.
 
 
 
A way to more accurately emulate air drag, then, is this:
 
<nowiki>
 
if (Y Speed < 0 && Y Speed > -4)
 
{
 
    X Speed -= ((X Speed div 0.125) / 256);
 
}
 
</nowiki>
 
  
The difference between the two methods, however, is pretty negligible, the second is just technically more accurate.
+
More pseudo-code:
  
Air drag is calculated each step before ''grv'' is added to Y Speed.
+
  X Speed -= jmp * sin(Ground Angle)
 +
  Y Speed -= jmp * cos(Ground Angle)
  
==Jump Velocity==
+
Notice how the jump values are subtracted from the X Speed and Y Speed. This means his 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.
 
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?
 
So how does variable jump height work?
  
When Sonic is standing upon the ground, and you press the jump button, Y Speed is set to Y Speed minus ''jmp'' (on flat ground, but jumping at angles is further described in [[SPG:Solid_Tiles#Jumping_At_Angles|Jumping At Angles]]. The following still applies). In a game without variable jump heights, there would be no subsequent calculations besides gravity, and the character's velocity would be steadily depleted by gravity.  The result would be a jump that lasted almost exactly 1 second and 100 pixels high.  In fact, this is the kind of jump Sonic makes if you keep the jump button held until he reaches the apex of his trajectory.  But the trick that allows variable jump height is all about releasing the button.
+
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.
 
 
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, Sonic 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 Sonic is moved to his new position and ''grv'' is added to Y Speed.
+
The check to see if the button is not being held is performed before the Player is moved to his new position and ''grv'' is added to Y Speed.
  
 
===Other characters===
 
===Other characters===
Tails' jumping is identical to Sonic's, but Knuckles jumps a little lower. This is caused by a slightly smaller value for ''jmp'', ''knxjmp''.
+
The Player's jump force (jmp) varies depending on the character, these differences are detailed in [[SPG:Characters|Characters]].
  
 
===Bugs when Jumping===
 
===Bugs when Jumping===
Because Sonic 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.
+
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 computer checks to see if you press the jump button before moving Sonic.  If you do press the jump button, it exits the rest of the cycle - so Sonic doesn't move at all during the step in which you jump, vertically or horizontally.  This is lame, because X Speed isn't lost, so he should continue to move.  This flaw can be buffed out in a new engine.
+
Disturbingly, the computer 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.
  
 
[[Image:SPGJumpDelay.gif]]
 
[[Image:SPGJumpDelay.gif]]
  
This can mean that in the next step it can detect a release of the jump button and Sonic will move up at a Y Speed of -4 without having ever moved up at the speed of ''jmp''.
+
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 ''jmp''.
  
As described in [[SPG:Solid_Tiles#Sensors|Sensors]] Sonic's sensor arrangement will change in size depending on what he's doing. When rolling/jumping, this arrangement becomes smaller. Whenever this happens, Sonic will move up or down by 5px to keep his bottom most pixel in the same position.
+
As described in [[SPG:Solid_Tiles#Sensors|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 in Sonic 2, when you are rolling and perform a jump, Sonic's collision size '''incorrectly''' becomes it's standing size rather than the smaller rolling size. This in turn causes a few bizarre issues.  
+
However in Sonic 2, 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 Sonic is in his ball form, he will still 'uncurl' when he lands, and this involves setting the mask to standing height and subtracting 5 from Y Positoon. This of course will simply move Sonic's bottom most pixel up by 5 if his sensors don't change size.  
+
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 Sonic lands from this jump, it just assumes his sensor is becoming big again, so 5px is subtracted from his Y Positoon. However because his sensors didn't change at all and Sonic was already at floor level, he just rises 5px above the floor instantly upon landing.
+
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.
  
 
[[Image:SPGRollingJumpLandBug.gif]]
 
[[Image:SPGRollingJumpLandBug.gif]]
  
This results in him making contact with the floor, then being moved up 5px then falling back down slowly via gravity.
+
This results in them making contact with the floor, then being moved up 5px then falling back down slowly via gravity.
  
 
[[Category:Sonic Physics Guide|Jumping]]
 
[[Category:Sonic Physics Guide|Jumping]]

Revision as of 14:46, 4 April 2021

Notes:

Research applies to all four of the Sega Mega Drive games, and Sonic CD.

The following only applies when Sonic is out of water land with no special power-ups. Water physics, Super Sonic, and Speed Shoes will be covered in separate guides.

Air Acceleration

When the Player is airborne, they can accelerate twice as fast as on land (air).

There is no friction in the air (but there is a complicated drag effect that will be explained later), and pretty much, once the Player has a certain X Speed in the air, they'll just keep going at that speed until you tell them otherwise or they hit a wall.

Furthermore, there is no distinction for deceleration in the air, either, so pressing Left simply subtracts air from X Speed no matter what, and pressing Right adds air to X Speed.

Sonic's top speed (top) is the same in the air as on the ground.

Gravity

Gravity (grv) is added to Y Speed in every step in which the Player isn't on the ground. It's what makes them fall downward when they run off of cliffs. It's also what stops them from moving upward forever when they jump.

Top Y Speed

In Sonic 1, the Player's Y Speed does not seem to be limited. As they fall, grv continues to be added to Y Speed, increasing indefinitely.

In Sonic CD, however, a limit was introduced so that Y Speed does not exceed 16 pixels per step. This limit is important so that the Player never outruns the camera, or passes through solid ground because they're moving so fast per step that they never even collide with it. Most likely introduced in Sonic CD because of the increased height in the design of levels such as Collision Chaos, and the endless vertical shaft in Tidal Tempest. Without the limit, the Player would accelerate to ridiculous velocities in some of these areas and probably break the game.

Y Speed += grv
if (Y Speed > 16) Y Speed = 16

Air Drag

Each step the Player is in the air, a special formula is performed on their's X Speed, but only if certain conditions are met. First, Y Speed must be negative. Second, Y Speed must be more than -4 (e.g. -3, or -3.5, is "more" than -4).

if (Y Speed < 0 && Y Speed > -4)
{
    X Speed -= ((X Speed div 0.125) / 256);
}

Air drag is calculated each step before grv is added to Y Speed.

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 jmp - they need to jump away from the Ground Angle they're standing on. Instead, both X Speed and Y Speed must have jmp subtracted from them, using cos() and sin() to get the right values.

More pseudo-code:

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

Notice how the jump values are subtracted from the X Speed and Y Speed. This means his 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 grv is added to Y Speed.

Other characters

The Player's jump force (jmp) varies depending on the character, these differences are detailed in Characters.

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 computer 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.

SPGJumpDelay.gif

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 jmp.

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 in Sonic 2, 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.

SPGRollingJumpLandBug.gif

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