Actions

Difference between revisions of "SPG:Slope Physics"

From Sonic Retro

m (Moved braking animation info to animation page)
m (Note on asymmetric angle ranges)
 
(47 intermediate revisions by 4 users not shown)
Line 1: Line 1:
 +
{{SPGPages}}
 
'''Notes:'''
 
'''Notes:'''
*The research applies to all four of the [[Sega Mega Drive]] games and ''[[Sonic CD]]''.
+
*''The research applies to all four of the [[Sega Mega Drive]] games and [[Sonic CD]]''.
 
+
*''This guide relies on information about tiles and sensors discussed in [[SPG:Solid_Tiles|Solid Tiles]]''.
*This guide relies on information about tiles and sensors discussed in [[SPG:Solid_Tiles|Solid Tiles]]
+
*''This page is essentially part 2 of 2. This details Player physics and speeds when on slopes. For part 1, describing the Player's terrain collision and 360 degree wall and ceiling collision, go to [[SPG:Slope_Collision|Slope Collision]]''.
 
 
*Following only describes how [[Sonic the Hedgehog|Sonic]] collides and interacts with solid tiles. Solid objects, such as [[Monitor|Monitors]], Moving Platforms, and Blocks each have their own collision routines with Sonic and don't necessarily behave exactly the same as the tiles do. For this, refer to [[SPG:Solid_Objects|Solid Objects]].
 
 
 
*Variables and constants for Sonic and other characters such as ''xpos'' and ''acc'' will be referenced frequently, they can be found in [[SPG:Basics|Basics]].
 
  
 
==Introduction==
 
==Introduction==
Once you have Sonic able to collide with solid tiles, he needs to move correctly over the terrian surface with momentum and physics. Knowing how sensors work will allow Sonic move smoothly over terrain with different heights, and knowing how Sonic's ground speed is affected by inputs to walk will allow him to move left and right, but that is not all there is to the engine.  
+
Once you have the Player object able to collide with solid tiles, they need to move correctly over the terrain surface with momentum and physics. Knowing how sensors work will allow the Player move smoothly over terrain with different heights, and knowing how the Player's ground speed is affected by inputs to walk will allow them to move left and right, but that is not all there is to the engine.  
This guide will explain how Sonic reacts to certain angles, and how 360 degree movement with momentum is acheived.
+
This guide will explain how the Player reacts to certain angles, and how 360 degree movement with momentum is achieved.
  
==Moving At Angles==
+
==Slope Momentum==
 +
The Player's movement across the stage has to be influenced by angled ground in order to feel realistic.
  
Sonic's speed has to be attenuated by angled ground in order to be realistic.
+
===Moving Along Slopes===
 +
{| class="prettytable" style="width: auto;"
 +
!Constant
 +
!Value
 +
|-
 +
|'''acceleration_speed'''
 +
|''0.046875 (12 subpixels)''
 +
|-
 +
|'''deceleration_speed'''
 +
|''0.5 (128 subpixels)''
 +
|-
 +
|'''friction_speed'''
 +
|''0.046875 (12 subpixels)''
 +
|-
 +
|'''top_speed'''
 +
|''6''
 +
|-
 +
|'''gravity_force'''
 +
|''0.21875 (56 subpixels)''
 +
|}
  
There are two ways in which Sonic's ground speed is affected on angles. The first will make sure that he does not traverse a hill in the same amount of time as walking over flat ground of an equal width. The second will slow him down when going uphill and speed him up when going downhill. Let's look at each of these in turn.
+
In order for angled movement to be accurate, we need to make sure that the Player does not traverse an incline slope in the same amount of time as walking over flat ground of an equal width.
  
===The Three Speed Variables===
+
If Sonic were a simple "slope-less" platformer that required nothing but flat blocks, you would only need two speed variables: '''''X Speed''''' and '''''Y Speed''''', the horizontal and vertical components of the Player's velocity. '''acceleration_speed''', '''deceleration_speed''', and '''friction_speed''' are added to '''''X Speed'''''; jump/bounce velocity and '''gravity_force''' are added to '''''Y Speed''''' (when the Player is in the air).
  
If Sonic were a simple platformer that required nothing but blocks, you would only need two speed variables: X speed (''xsp'') and Y speed (''ysp''), the horizontal and vertical components of Sonic's velocity. Acceleration (''acc''), deceleration (''dec''), and friction (''frc'') are added to ''xsp''; jump/bounce velocity and gravity (''grv'') are added to ''ysp'' (when Sonic is in the air).
+
But when slopes are involved, while the Player moves along a slope, they're moving both horizontally and vertically. This means that both '''''X Speed''''' and '''''Y Speed''''' have a non-zero value. Simply adding '''acceleration_speed''', '''deceleration_speed''', or '''friction_speed''' to '''''X Speed''''' no longer works; imagine the Player was trying to run up a wall - adding to their horizontal speed would be useless because they need to move upward.
  
But when slopes are involved, while Sonic moves along a slope, he's moving both horizontally and vertically. This means that both ''xsp'' and ''ysp'' have a non-zero value. Simply adding ''acc'', ''dec'', or ''frc'' to ''xsp'' no longer works; imagine Sonic was trying to run up a wall - adding to his horizontal speed would be useless because he needs to move upward.
+
The trick is to employ a third speed variable (as the original engine does), '''''Ground Speed'''''. This is the speed of the Player along the ground, disregarding '''''Ground Angle''''' altogether. '''acceleration_speed''', '''deceleration_speed''', and '''friction_speed''' are applied to '''''Ground Speed''''', not '''''X Speed''''' or '''''Y Speed'''''.
  
The trick is to employ a third speed variable (as the original engine does), so let's call it Ground speed (''gsp''). This is the speed of Sonic along the ground, disregarding ''ang'' altogether. ''acc'', ''dec'', and ''frc'' are applied to ''gsp'', not ''xsp'' or ''ysp''.
+
While on the ground, '''''X Speed''''' and '''''Y Speed''''' are entirely derived from '''''Ground Speed''''' every step before the Player is moved. Perhaps a code example is in order:
  
While on the ground, ''xsp'' and ''xsp'' are derived from ''gsp'' every step before Sonic is moved. Perhaps a pseudo-code example is in order:
+
<syntaxhighlight>// Calculate X and Y Speed from Ground Speed
 +
X Speed = Ground Speed * cos(Ground Angle)
 +
Y Speed = Ground Speed * -sin(Ground Angle)
  
  xsp = gsp*cos(angle);
+
// Actually move via X Speed and Y Speed
  ysp = gsp*-sin(angle);
+
X Position += X Speed;
 
+
Y Position += Y Speed;</syntaxhighlight>
  xpos += xsp;
 
  ypos += ysp;
 
  
No matter what happens to the ''ang'', ''gsp'' is preserved, so the engine always knows what speed Sonic is "really" moving at.
+
No matter what happens to the '''''Ground Angle''''', '''''Ground Speed''''' is preserved, so the game always knows what speed the Player is "really" moving at.
  
===Slope Factor===
+
What's more, is that the position the Player is moved to with '''''X Speed''''' and '''''Y Speed''''' are where the player will next check for collision with the floor, so it is vital that the next position the player moves to for the next frame's checks aligns as much with the current slope direction as possible.
  
By this point, Sonic should be able to handle any hills with an accurate velocity but he still needs to slow down when going uphill and speed up when going downhill.
+
===Slowing Down Uphill And Speeding Up Downhill===
 +
By this point, the Player should be able to handle any basic hills with an accurate angular motion, however they still need to slow down when going uphill and to speed up when going downhill. This is essentially a "gravity" being applied while on the ground, and is what makes slopes hard to climb but easy to run down. Fortunately, this is simple to achieve - with something called the '''''Slope Factor'''''.  
  
Fortunately, this is simple to achieve - with something called the Slope Factor (''slope''). Just subtract ''slope''*sin(''ang'') from ''gsp'' at the beginning of every step.  
+
While the player moves along slopes, a value called '''''Slope Factor''''' is used to modify the Player's '''''Ground Speed'''''. Just subtract <code>'''''Slope Factor''''' * sin('''''Ground Angle''''')</code> from '''''Ground Speed''''' at the beginning of every step. This only happens if the Player is ''not'' in [[SPG:Slope_Collision#The_Four_Modes|Ceiling mode]].  
  
  gsp -= slope*sin(ang);
+
What is the value of Slope Factor?
  
The value of ''slope'' is always ''slp'' when running, but not so when rolling. When Sonic is rolling uphill (the sign of ''gsp'' is equal to the sign of sin(''ang'')), ''slope'' is ''slprollup'' ($001E). When Sonic is rolling downhill (the sign of ''gsp'' is '''not''' equal to the sign of sin(''ang'')), ''slope'' is ''slprolldown'' ($0050).
+
{| class="prettytable" style="width: auto;"
 +
!Constant
 +
!Value
 +
|-
 +
|'''slope_factor_normal'''
 +
|''0.125 (32 subpixels)''
 +
|-
 +
|'''slope_factor_rollup'''
 +
|''0.078125 (20 subpixels)''
 +
|-
 +
|'''slope_factor_rolldown'''
 +
|''0.3125 (80 subpixels)''
 +
|}
  
'''Note:''' In Sonic 1, it appears that ''slope'' doesn't get added if Sonic is stopped and in his standing/waiting cycle. But in Sonic 3 & Knuckles, ''slope'' seems to be added even then, so that Sonic can't stand on steep slopes - they will force him to walk them down.
+
The value of '''''Slope Factor''''' is always '''slope_factor_normal''' when running, but not so when rolling. When the Player is rolling uphill (the sign of Ground Speed is equal to the sign of <code>sin('''''Ground Angle''''')</code>), Slope Factor is '''slope_factor_rollup'''. When the Player is rolling downhill (the sign of Ground Speed is ''not'' equal to the sign of <code>sin('''''Ground Angle''''')</code>), '''''Slope Factor''''' is '''slope_factor_rolldown'''.
  
==Jumping At Angles==
+
Note:
 +
* In Sonic 1 and 2, walking/running '''''Slope Factor''''' doesn't get subtracted if the Player is stopped ('''''Ground Speed''''' is ''0''). But in Sonic 3 & Knuckles, if '''''Ground Speed''''' is ''0'', the game will still subtract '''''Slope Factor''''' if the value of it is greater than or equal to ''0.05078125 (13 subpixels)''. So that the Player can't stand on steep slopes - it will force them to walk down. Rolling slope factor, however, has no check for if '''''Ground Speed''''' is ''0'' in any of the games.
  
Jumping is also affected by the angle Sonic is at when he does it. He can't simply set ''ysp'' to negative ''jmp'' - he needs to jump away from the angle he's standing on. Instead, both ''xsp'' and ''ysp'' must have ''jmp'' subtracted from them, using cos() and sin() to get the right values.
+
==360 Degree Movement==
 +
So the Player can run over basic hills and ramps and ledges, and motion will be adjusted based on the angle.
  
More pseudo-code:
+
As explained in [[SPG:Slope Collision#360 Degree Collision|Slope Collision]], at steep enough angles the Player's collision setup changes mode (entirely rotates).
  
  xsp -= jmp*sin(angle);
+
{| class="prettytable" style="width: auto;"
  ysp -= jmp*cos(angle);
+
|style="text-align:center;"|[[Image:SPGModes.gif]]
 +
|-
 +
!The Player's collision modes.
 +
|}
  
Notice how the jump values are subtracted from the ''xsp'' and ''ysp''. 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.
+
With that taken care of, the appropriate '''''Ground Angle''''' will be read at slopes of any direction, and the slope factor will continue to work based on this angle.  
  
==Switching Mode==
+
So at this point, overall slope movement for all 360 degrees will work rather well. However, it's not enough just to slow the Player down on steep slopes using Slope Factor. They need to slip back (or even fall down) when it gets too steep and they are moving too slowly.
  
So Sonic can run over hills and ramps and ledges, and all that is great. But it is ''still'' not enough. He cannot make his way from the ground to walls and ceilings without more work.
+
===Falling and Slipping Down Slopes===
 +
If moving too slowly on steep slopes, the Player will briefly lose horizontal control and detach from the ground. This ensures you can't walk slowly on ceilings, or slowly/gradually climb a slope forever.
  
Why not? Well, because sensor <span style="color:#00f000; font-weight: bold;">A</span> and <span style="color:#38ffa2; font-weight: bold;">B</span> check straight downward, finding the height of the ground. There is just no way they can handle the transition to walls when everything is built for moving straight up and down on the Y-axis.
+
The requirements for this differ in Sonic 3 onwards.
  
How can we solve this? By using four different modes of movement. This will take a little explaining.
+
====Sonic 1, 2, and CD Method====
 +
The angle range of slopes for slipping is when your '''''Ground Angle''''' is steeper than 45 degrees:
 +
{| class="prettytable" style="width: auto;"
 +
!Range
 +
!Values
 +
|-
 +
|Slipping and Falling
 +
|
 +
''46° (223)'' to ''315° (32)''
 +
|}
  
===The Four Modes===
+
[[Image:SPGSlipFallRange.png]] <br>
 +
Note: ''These angle ranges are not perfectly symmetrical, this is due to the efficient calculation used in the original game, rather than an intentional difference.''
  
It seems pretty reasonable to assume that, because Sonic can traverse ground in 360 degrees, the engine handles all 360 degrees in much the same way. But, in fact, the engine splits the angles into four quadrants, greatly simplifying things.
+
In addition, the game will check if absolute '''''Ground Speed''''' falls below ''2.5 (2 pixels, 128 subpixels)''.
  
To better understand what I am talking about, imagine a simpler platformer without full loops, just a few low hills and ramps. All the character would need to do is, after moving horizontally, move up or down until they met the level of the floor. The angle of the floor would then be measured. The angle would be used to attenuate ''gsp'', but nothing more. The character would still always move horizontally and move straight up and down to adhere to floor level.
+
So, when these conditions are met, what happens? Well, the Player will slip. This achieved by detaching the Player from the floor (clearing the grounded state), setting '''''Ground Speed''''' to ''0'', and employing the [[SPG:Running#Control_Lock|control lock timer]].
  
This is much like how Sonic does things. Only, when ''ang'' gets too steep, Sonic switches "quadrant", moving from Floor mode to Right Wall mode (to Ceiling mode, to Left Wall mode, and back around to Floor mode, etc). At any one time, in any one mode, Sonic behaves like a simpler platformer. The magic happens by combining all four modes, and cleverly switching between them smoothly.
+
{| class="prettytable" style="width: auto;"
 +
|style="text-align:center;"|[[Image:SPGSlopeSlip.gif]]
 +
|-
 +
!Next to Sonic you can see the control lock timer.
 +
|}
 +
Here, when he gets too steep, Sonic detaches from the floor, '''''Ground Speed''''' is set to ''0'', and control lock timer is set.
  
So how and when does Sonic switch mode?
+
But wait, why does Sonic not stop dead in his tracks if he become airborne and '''''Ground Speed''''' was set to 0? Well, if the floor isn't steep enough to freely fall from, the Player will immediately land back onto the floor and the '''''Ground Speed''''' will be restored from '''''X/Y Speed''''' as normal. Landing on the floor and speed conversion is further detailed up ahead in [[SPG:Slope Physics#Landing On The Ground|Landing On The Ground]])
  
When in Floor mode, and ''ang'' is steeper than 45° ($E0), the engine switches into Right Wall mode. Everything is basically the same, only the sensors check to the right instead of downward, and Sonic is moved to "floor" level horizontally instead of vertically.
+
Okay, what about if the Player is on an even steeper floor?
  
Now that he's in Right Wall mode, if ''ang'' is shallower than 45° ($E0), the engine switches back into Floor mode.
+
[[Image:SPGSlopeFall.gif]]
  
The other transitions work in exactly the same way, with the switch angles relative to the current mode.
+
You can notice he detaches from the floor and control lock is set. It doesn't tick down until he lands, and even after the timer has begun, when he crosses the gap the timer pauses. The code for both the control lock timer and the slipping are only ran when grounded.
  
When the mode is being calculated, it simply checks which quadrant Sonic's ''ang'' is currently in, which will place Sonic in the correct mode (ranges are inclusive):
+
So, what about the timer? When the Player falls or slips off in the manner described above, the [[SPG:Running#Control_Lock|control lock timer]] is set to ''30'' (it won't begin to count down until the Player lands back on the ground). While this timer is non-zero and the Player is on the ground, it prevents directional input from adjusting the Player's speed with the left or right buttons. The timer counts down by one every step when grounded, so the lock lasts about half a second. During this time only '''slope_factor_normal''' and the speed the Player fell back on the ground with is in effect, so the Player will slip back down the slope.
  
  Floor Mode (start of rotation)
+
In the above first example gif, you may notice the control lock timer counts down twice, this is purely because Sonic happened to be too steep and too slow still when the timer ended initially, and he slipped once again, seamlessly.
  0° to 45° (1~32) ($FF~$E0)
 
  
  Right Wall Mode
+
So, with some example code, it works like the following:
  46° to 134° (33~95) ($DF~$A1)
+
<syntaxhighlight>// Is player grounded?
 +
if player is grounded
 +
{
 +
    if control_lock_timer == 0
 +
    {
 +
        // Should player slip and fall?
 +
        if abs(Ground Speed) < 2.5 and (Ground Angle is within the slipping and falling range)
 +
        {
 +
            // Detach (fall)
 +
            grounded = false;
 +
           
 +
            // Lock controls (slip)
 +
            Ground Speed = 0;
 +
            control_lock_timer = 30;
 +
        }
 +
    }
 +
    else
 +
    {
 +
        // Tick down timer
 +
        control_lock_timer -= 1;
 +
    }
 +
}</syntaxhighlight>
  
  Ceiling Mode
 
  135° to 225° (96~160) ($A0~$60)
 
  
  Left Wall Mode
+
====Sonic 3 Method====
  226° to 314° (161~223) ($5F~$21)
 
  
  Floor Mode (end of rotation)
+
Sonic 3 works a little differently, where Sonic will slip down at angles ''even shallower'' than ''45°'', and only detach from the floor when at angles ''even steeper'' than ''45°''.
  315° to 360° (224~256) ($20~$00)
 
  
''Note: Since the classic games don't use degrees, and rather have angles ranging from 0 to 256, both approximate degree values and a more accurate decimal representation of the Hex values are included.''
+
{| class="prettytable" style="width: auto;"
 +
!Range
 +
!Values
 +
|-
 +
|Slipping
 +
|'''''Ground Angle''''' is within the range ''35° (231) to 326° (24)'' inclusive.
 +
|-
 +
|Falling
 +
|'''''Ground Angle''''' is within the range ''69° (207) to 293° (48)'' inclusive.
 +
|}
  
These ranges are symmetrical for left and right, but does favour the floor and ceiling modes, with their ranges being a degree or two wider.
+
[[Image:SPGSlipFallRangeS3.png]] <br>
 +
Note: ''These angle ranges are not perfectly symmetrical, this is due to the efficient calculation used in the original game, rather than an intentional difference.''
  
You might rightly ask where the ground sensors are when in Right Wall mode. They're in exactly the same place, only rotated 90 degrees. Sensor <span style="color:#00f000; font-weight: bold;">A</span> is now at Sonic's ''ypos''+9 instead of ''xpos''-9. Sensor <span style="color:#38ffa2; font-weight: bold;">B</span> is now at Sonic's ''ypos''-9, instead of ''xpos''+9. Instead of vertical sensor lines, they are now horizontal, stretching 16 pixels beyond his foot level (which is now 20 pixels "below" him, at ''xpos''+20).
+
Not only are there these new ranges, '''''Ground Speed''''' is now modified by ''0.5'' instead of being set to ''0''. The '''''Ground Speed''''' threshold remains at ''2.5 (2 pixels, 128 subpixels)''.
  
Yes, because the sensors move so far, it is possible for Sonic to be "popped" out to a new position in the step in which he switches mode. However, this is hardly ever more than a few pixels and really isn't noticeable at all during normal play. To adjust for this in a new engine, an alternative method to switch mode would be to check for solid ground using a 90 degree rotated mask. For example, standing upright on flat ground, the left side would check rotated 90 degrees for steep slopes to switch to Left Wall Mode, and the right would check rotated -90 degrees for steep slopes to switch to Right Wall Mode. Only the lower ground sensor of the rotated mask would need to check for ground. This would have to exclude walls so Sonic doesn't begin walking on a wall when he gets near one, but would mean Sonic switched mode sooner on a slope which means less "popping".
+
Here's how it works:
  
One more thing: I said that solid tiles were made of height arrays. Operative word: ''height''. How do they work when in Right Wall mode? Well, rather gobsmackingly, it turns out that in the original engine, each solid tile has ''two'' complementary height arrays, one used for when moving horizontally, the other for when moving vertically.
+
<syntaxhighlight>// Is the Player grounded?
 
+
if player is grounded
What about Left Wall and Ceiling mode? Wouldn't there need to be ''four'' height arrays? No, because tiles of those shapes simply use normal height arrays, just inverted. When in Ceiling mode, Sonic knows that the height value found should be used to move him down and not up.
+
{
 
+
    if control_lock_timer == 0
<div class="large-12 columns" style="padding:0px">
+
    {
<div class="large-6 columns" style="padding:0px">
+
        // Should player slip?
With these four modes, Sonic can go over all sorts of shapes. Inner curves, outer curves, you name them. Here are some approximate example images with their angle values to help give you some idea of what this results in:
+
        if abs(Ground Speed) < 2.5 and (Ground Angle is within slip range)
 
+
        {
[[Image:SPGInnerCurve.PNG|link=Special:FilePath/SPGInnerCurve.PNG]] [[Image:SPGInnerCurveChart.PNG|link=Special:FilePath/SPGInnerCurveChart.PNG]]
+
            // Lock controls (slip)
 
+
            control_lock_timer = 30;
You can observe Sonic's mode changing on the frame after his floor angle (''ang'') exceeds 45°. Sonic's position shifts a bit when the change occurs, due to the totally new collision angle and position.
+
           
 
+
            // Should player fall?
</div>
+
            if (Ground Angle is within fall range)
<div class="large-6 columns">
+
            {
[[Image:SPGOuterCurve.PNG|link=Special:FilePath/SPGOuterCurve.PNG]] [[Image:SPGOuterCurveChart.PNG|link=Special:FilePath/SPGOuterCurveChart.PNG]]
+
                // Detach (fall)
 
+
                grounded = false;
You may notice Sonic's mode switches erratically on the convex curve, this is because his floor angle (''ang'') will suddenly decrease when switching to wall mode, causing it to switch back and forth until he is far enough down the curve to stabilise. This isn't usually noticeable, and happens less the faster you are moving.
+
            }
</div>
+
            else
</div>
+
            {
 
+
                // Depending on what side of the player the slope is, add or subtract 0.5 from Ground Speed to slide down it
Note: The reason the gifs show the mode switch being the frame ''after'' the angle threshold is reached is simply because the collision being shown is the one used for ''that'' frame, ''before'' Sonic's ''ang'' updates.
+
                if Ground Angle < 180°
 
+
                {
===When to Change Mode===
+
                    Ground Speed -= 0.5;
 
+
                }
If you've checked the guide regarding the [[SPG:Main_Game_Loop|Main Game Loop]] you may notice the mode switching isn't mentioned at all, that's because the game doesn't actually ever "switch" his mode. Sonic's current "mode" is decided right before collision occurs. It will measure his angle, and decide which mode of collision to use right there and then. There is no "Mode" state stored in memory. So effectively, Sonic's mode changes whenever his angle (''ang'') does.
+
                else
 
+
                {
Since the floor angle (''ang'') is decided ''after'' floor collision (as a result of floor collision) the floor collision that frame has to use the previous frames angle, even though Sonic has moved to a new part of the slope since then. This results in Sonic's mode effectively changing 1 frame ''after'' Sonic reaches one of the 45 degree angle thresholds.
+
                    Ground Speed += 0.5;
 
+
                }
===Falling and Sliding Off Of Walls And Ceilings===
+
            }
 
+
        }
When in Right Wall, Left Wall, or Ceiling mode and Sonic's ''ang'' is between 90 and 270, Sonic will fall any time absolute ''gsp'' falls below ''fall'' ($0280) (''gsp'' is set to 0 at this time, but ''xsp'' and ''ysp'' are unaffected, so Sonic will continue his trajectory through the air). This happens even if there is ground beneath him. If Sonic is in Right Wall, Left Wall, or Ceiling Mode but Sonic's ''ang'' is not between 90 and 270 then the horizontal control lock timer described below will still be set to 30 but Sonic will not enter a falling state remaining in his current state.
+
    }
 
+
     else
====Horizontal Control Lock====
 
 
 
When Sonic falls or slides off in the manner described above, the [[SPG:Springs and Things#Horizontal Control Lock|horizontal control lock]] timer is set to 30 ($1E) (it won't begin to count down until Sonic lands back on the ground). While this timer is non-zero and Sonic is on the ground, it prevents the player from adjusting Sonic's speed with the left or right buttons. The timer counts down by one every step, so the lock lasts about half a second. During this time only ''slp'' and the speed Sonic fell back on the ground with is in effect, so Sonic will slip back down the slope.
 
 
 
  if (abs(gsp) < 2.5 && (angle >= 45 && angle <= 315))
 
  {
 
     if (angle >= 90 && angle <= 270)
 
 
     {
 
     {
      floor_mode = 0;
+
        // Tick down timer
      gsp = 0;
+
        control_lock_timer -= 1;  
 
     }
 
     }
    horizontal_lock_timer = 30;
+
}</syntaxhighlight>
  }
 
 
 
==The Air State==
 
 
 
Any time Sonic is in the air, he doesn't have to worry about angles, ''gsp'', ''slp'', or any of that jazz. All he has to do is move using ''xsp'' and ''ysp'' until he detects the ground, at which point he re-enters the ground state.
 
 
 
===Jumping "Through" Floors===
 
  
There are some ledges that Sonic can jump up "through". These are often in the hilly, green zones such as [[Green Hill Zone (Sonic the Hedgehog 16-bit)|Green Hill Zone]], [[Emerald Hill Zone]], [[Palmtree Panic Zone]], and so on. The solid tiles that make up these ledges are flagged by the engine as being a certain type that should only be detected by Sonic's <span style="color:#00f000; font-weight: bold;">A</span> and <span style="color:#38ffa2; font-weight: bold;">B</span> sensors. They are ignored entirely by C and D as well as the horizontal sensor line. Finally, sensor <span style="color:#00f000; font-weight: bold;">A</span> and <span style="color:#38ffa2; font-weight: bold;">B</span> (mostly) only detect the floor when Sonic is moving downwards (but always while on the ground). So with a slightly shorter jump, you will see Sonic 'pop' upwards onto a jump through surface once he begins to fall.
+
==Landing On The Ground==
 +
While the Player is grounded, both '''''X Speed''''' and '''''Y Speed''''' are constantly derived from '''''Ground Speed'''''. When they fall or otherwise leave the ground, '''''X Speed''''' and '''''Y Speed''''' are already the correct values for them to continue their trajectory through the air. But when they land back on the ground, a new '''''Ground Speed''''' value must be calculated from the '''''X Speed''''' and '''''Y Speed''''' that they have upon impact.
  
===Reacquisition Of The Ground===
+
While airborne moving downwards the moment your [[SPG:Slope_Collision#Landing_On_A_Floor|airborne Ground Sensors]] collide with the floor, a winning angle value is found by the airborne Ground Sensors, and the Player will land.  
Both ''xsp'' and ''ysp'' are derived from ''gsp'' while Sonic is on the ground. When he falls or otherwise leaves the ground, ''xsp'' and ''ysp'' are already the proper values for him to continue his trajectory through the air. But when Sonic lands back on the ground, ''gsp'' must be calculated from the ''xsp'' and ''ysp'' that he has when it happens.
+
In the same way, when you are moving upwards and your [[SPG:Slope_Collision#Landing_On_A_Ceiling|Ceiling Sensors]] collide with a ceiling, a winning angle value is found by the Ceiling Sensors, and the Player will attempt to land.  
You might think that they would use cos() and sin() to get an accurate value, but that is not the case. In fact, something much more basic happens, and it is different when hitting into a curved ceiling as opposed to landing on a curved floor, so I will cover them separately.
 
  
As you land the angle of the ground you touch is read (''ang'').
+
'''Notes''':
The following covers the angle (''ang'') of the ground (floor or ceiling) that Sonic touches as he lands, and only happens the frame when he lands when changing from in air to on ground.
+
*This section describes physics during the moment the Player collides with floors and ceilings while airborne, and then transitions from being airborne to being grounded. For how the Player generally collides with the terrain while grounded, see [[SPG:Slope_Collision#Ground_Sensors_.28Grounded.29|Ground Sensors]] and [[SPG:Slope_Physics#360_Degree_Movement|360 Degree Movement]], and for slope physics & momentum while grounded, see [[SPG:Slope_Physics#Slope_Momentum|Slope Momentum]].
 +
*This section explains the physics side of things, for more information about the collision side of things, see [[SPG:Slope_Collision#Landing_On_A_Floor|Landing On A Floor]] and [[SPG:Slope_Collision#Landing_On_A_Ceiling|Landing On A Ceiling]].
 +
*Some of the reactions described ahead are in part determined by what direction the Player was moving in the air, which is the same calculation as noted in [[SPG:Slope_Collision#Airborne_Sensor_Activation|Airborne Sensor Activation]].
  
''Note: Since the classic games don't use degrees, and rather have angles ranging from 0 to 256, both approximate degree values and a more accurate (and inverted) decimal representation of the Hex values are included.''
+
===When Falling Downward===
 +
When the Player [[SPG:Slope_Collision#Landing_On_A_Floor|lands on a floor]], they will become grounded, a winning angle will be found by the airborne Ground Sensors. Based on this angle, '''''Ground Speed''''' will be set differently.
  
====When Falling Downward====
+
[[Image:SPGLandFloor.png|link=Special:FilePath/SPGLandFloor.png]]<br>
[[Image:SPGLandFloor.png|link=Special:FilePath/SPGLandFloor.png]]
+
Note: ''These angle ranges are not perfectly symmetrical, this is due to the efficient calculation used in the original game, rather than an intentional difference.''
  
The following ranges are inclusive.
+
The following ranges are inclusive (smaller ranges override larger ranges).
<div class="large-12 columns" style="padding:0px">
+
{| class="prettytable" style="width: auto;"
<div class="large-4 columns" style="padding:0px">
+
!Range
'''Shallow:'''
+
!Values
When ''ang'' is in the range of
+
!Result
 +
|-
 +
|
 +
Flat
 +
|
 +
''0° (255)'' to ''23° (240)''
  
  0° to 23° (1~16) ($FF~$F0)
+
and mirrored:
  and mirrored:
+
''339° (15)'' to ''360° (0)''
  339° to 360° (241~256) ($0F~$00)
+
|
 +
The floor landed on is very flat, so '''''Ground Speed''''' can just be set based on the Player's '''''X Speed''''':
  
''gsp'' is set to the value of ''xsp''.
+
'''''Ground Speed''''' is set to the value of '''''X Speed'''''. '''''Ground Angle''''' is set to the angle found by the floor sensors.
</div>
+
|-
<div class="large-4 columns">
+
|
'''Half Steep:'''
+
Slope
When ''ang'' is in the range of
+
|
 +
''0° (255)'' to ''45° (224)''
  
  24° to 45° (17~32) ($EF~$E0)
+
and mirrored:
  and mirrored:
+
''316° (31)'' to ''360° (0)''
  316° to 338° (225~240) ($1F~$10)
+
|
 +
The slope landed on is slightly steep, so it will use '''''X Speed''''' if the Player was moving horizontally, but will calculate a new '''''Ground Speed''''' based on half of '''''Y Speed''''' if they were moving down:
  
''gsp'' is set to ''xsp'' but only if the absolute of ''xsp'' is greater than ''ysp''. Otherwise, ''gsp'' is set to ''ysp''*0.5*-sign(sin(''ang'')).
+
When moving mostly left or mostly right, '''''Ground Speed''''' is set to '''''X Speed'''''.
</div>
+
Otherwise, '''''Ground Speed''''' is set to <code>'''''Y Speed''''' * ''0.5'' * -sign(sin('''''Ground Angle'''''))</code>.
<div class="large-4 columns">
+
'''''Ground Angle''''' is set to the angle found by the floor sensors.
'''Full Steep:'''
+
|-
When ''ang'' is in the range of
+
|
 +
Steep
 +
|
 +
Any angle outside of Slope range
 +
|
 +
The slope landed on is very steep, so it will use '''''X Speed''''' if the Player was moving horizontally, but will calculate a new '''''Ground Speed''''' based on '''''Y Speed''''' if they were moving down:
  
  46° to 90° (33~64) ($DF~$C0)  
+
When moving mostly left or mostly right, '''''Ground Speed''''' is set to '''''X Speed'''''.
  and mirrored:
+
Otherwise, '''''Ground Speed''''' is set to <code>'''''Y Speed''''' * -sign(sin('''''Ground Angle'''''))</code>.
  271° to 315° (193~224) ($3F~$20)
+
'''''Ground Angle''''' is set to the angle found by the floor sensors.
 +
|}
  
''gsp'' is set to ''xsp'' but only if the absolute of ''xsp'' is greater than ''ysp''. Otherwise, ''gsp'' is set to ''ysp''*-sign(sin(''ang'')).
+
===When Going Upward===
</div>
+
When the Player [[SPG:Slope_Collision#Landing_On_A_Ceiling|lands on a ceiling]], a winning angle will be found by the sensors, and based on this angle, the reaction will be different.
</div>
 
  
====When Going Upward====
+
[[Image:SPGCeilingLand.gif]]
[[Image:SPGLandCeiling.png|link=Special:FilePath/SPGLandCeiling.png]]
 
  
The following ranges are inclusive.
+
When the Player contacts a steep slope above them, they may be able to land and continue along it. Otherwise, they will simply bump their head.
<div class="large-12 columns" style="padding:0px">
 
<div class="large-6 columns" style="padding:0px">
 
'''Slope:'''
 
When the ceiling ''ang'' detected is in the range of
 
  
  91° to 135° (65~96) ($BF~$A0)
+
[[Image:SPGLandCeiling.png|link=Special:FilePath/SPGLandCeiling.png]]<br>
  and mirrored
+
Note: ''These angle ranges are not perfectly symmetrical, this is due to the efficient calculation used in the original game, rather than an intentional difference.''
  226° to 270° (161~192) ($5F~$40)
 
  
Sonic reattaches to the ceiling and ''gsp'' is set to ''ysp''*-sign(sin(''ang'')).
+
The following ranges are inclusive (smaller ranges override larger ranges).
</div>
 
<div class="large-6 columns">
 
'''Ceiling:'''
 
When the ceiling ''ang'' is in the range of
 
  
  136° to 225° (97~160) ($9F~$60)
+
{| class="prettytable" style="width: auto;"
 +
!Range
 +
!Values
 +
!Result
 +
|-
 +
|
 +
Steep
 +
|
 +
Any angle outside of Flat range
 +
|
 +
The ceiling is quite steep and can be landed on:
  
Sonic hits his head like with any ceiling, and doesn't reattach to it. ''ysp'' is set to 0, and ''xsp'' is unaffected.
+
When moving mostly up, the Player reattaches to the ceiling (becomes grounded), '''''Ground Speed''''' is set to <code>'''''Y Speed''''' * -sign(sin('''''Ground Angle'''''))</code>, and '''''Ground Angle''''' is set to the angle found by the ceiling sensors.
</div>
+
Otherwise, when moving mostly left or mostly right, the Player simply bumps their head on the ceiling and doesn't reattach to it. '''''Y Speed''''' is set to ''0'', and '''''X Speed'''''/'''''Ground Speed'''''/'''''Ground Angle''''' are unaffected.
</div>
+
|-
 +
|
 +
Flat
 +
|
 +
''91° (191)'' to ''225° (66)''
 +
|
 +
The ceiling is too flat to land on:
  
===Air Rotation===
+
The Player simply bumps their head on the ceiling, and doesn't reattach to it. '''''Y Speed''''' is set to ''0'', and '''''X Speed'''''/'''''Ground Speed'''''/'''''Ground Angle''''' are unaffected.
When Sonic leaves a slope, such as running up and off a quarter pipe, Sonic's angle smoothly returns to 0.  
+
|}
  
Sonic's angle (''ang'') changes by
+
==Notes==
  2.8125° (2) ($2)
+
*''This page is essentially part 2 of 2. This details Player physics and speeds when on slopes. For part 1, describing the Player's terrain collision and 360 degree wall and ceiling collision, go to [[SPG:Slope_Collision|Slope Collision]]''.
each frame, in the direction towards 0.
 
*''Note: Degree angle is approximate, as the original game has angles ranging up to 256. Degree, decimal, and hex have been provided.''
 
*''Note: Regardless of Sonic's angle, Sonic's air sensors do not rotate. Air collision essentially ignores Sonic's mode.''
 
  
 
[[Category:Sonic Physics Guide]]
 
[[Category:Sonic Physics Guide]]

Latest revision as of 03:59, 21 July 2023

Sonic Physics Guide
Collision
Physics
Gameplay
Presentation
Special

Notes:

  • The research applies to all four of the Sega Mega Drive games and Sonic CD.
  • This guide relies on information about tiles and sensors discussed in Solid Tiles.
  • This page is essentially part 2 of 2. This details Player physics and speeds when on slopes. For part 1, describing the Player's terrain collision and 360 degree wall and ceiling collision, go to Slope Collision.

Introduction

Once you have the Player object able to collide with solid tiles, they need to move correctly over the terrain surface with momentum and physics. Knowing how sensors work will allow the Player move smoothly over terrain with different heights, and knowing how the Player's ground speed is affected by inputs to walk will allow them to move left and right, but that is not all there is to the engine. This guide will explain how the Player reacts to certain angles, and how 360 degree movement with momentum is achieved.

Slope Momentum

The Player's movement across the stage has to be influenced by angled ground in order to feel realistic.

Moving Along Slopes

Constant Value
acceleration_speed 0.046875 (12 subpixels)
deceleration_speed 0.5 (128 subpixels)
friction_speed 0.046875 (12 subpixels)
top_speed 6
gravity_force 0.21875 (56 subpixels)

In order for angled movement to be accurate, we need to make sure that the Player does not traverse an incline slope in the same amount of time as walking over flat ground of an equal width.

If Sonic were a simple "slope-less" platformer that required nothing but flat blocks, you would only need two speed variables: X Speed and Y Speed, the horizontal and vertical components of the Player's velocity. acceleration_speed, deceleration_speed, and friction_speed are added to X Speed; jump/bounce velocity and gravity_force are added to Y Speed (when the Player is in the air).

But when slopes are involved, while the Player moves along a slope, they're moving both horizontally and vertically. This means that both X Speed and Y Speed have a non-zero value. Simply adding acceleration_speed, deceleration_speed, or friction_speed to X Speed no longer works; imagine the Player was trying to run up a wall - adding to their horizontal speed would be useless because they need to move upward.

The trick is to employ a third speed variable (as the original engine does), Ground Speed. This is the speed of the Player along the ground, disregarding Ground Angle altogether. acceleration_speed, deceleration_speed, and friction_speed are applied to Ground Speed, not X Speed or Y Speed.

While on the ground, X Speed and Y Speed are entirely derived from Ground Speed every step before the Player is moved. Perhaps a code example is in order:

// Calculate X and Y Speed from Ground Speed
X Speed = Ground Speed * cos(Ground Angle)
Y Speed = Ground Speed * -sin(Ground Angle)

// Actually move via X Speed and Y Speed
X Position += X Speed;
Y Position += Y Speed;

No matter what happens to the Ground Angle, Ground Speed is preserved, so the game always knows what speed the Player is "really" moving at.

What's more, is that the position the Player is moved to with X Speed and Y Speed are where the player will next check for collision with the floor, so it is vital that the next position the player moves to for the next frame's checks aligns as much with the current slope direction as possible.

Slowing Down Uphill And Speeding Up Downhill

By this point, the Player should be able to handle any basic hills with an accurate angular motion, however they still need to slow down when going uphill and to speed up when going downhill. This is essentially a "gravity" being applied while on the ground, and is what makes slopes hard to climb but easy to run down. Fortunately, this is simple to achieve - with something called the Slope Factor.

While the player moves along slopes, a value called Slope Factor is used to modify the Player's Ground Speed. Just subtract Slope Factor * sin(Ground Angle) from Ground Speed at the beginning of every step. This only happens if the Player is not in Ceiling mode.

What is the value of Slope Factor?

Constant Value
slope_factor_normal 0.125 (32 subpixels)
slope_factor_rollup 0.078125 (20 subpixels)
slope_factor_rolldown 0.3125 (80 subpixels)

The value of Slope Factor is always slope_factor_normal when running, but not so when rolling. When the Player is rolling uphill (the sign of Ground Speed is equal to the sign of sin(Ground Angle)), Slope Factor is slope_factor_rollup. When the Player is rolling downhill (the sign of Ground Speed is not equal to the sign of sin(Ground Angle)), Slope Factor is slope_factor_rolldown.

Note:

  • In Sonic 1 and 2, walking/running Slope Factor doesn't get subtracted if the Player is stopped (Ground Speed is 0). But in Sonic 3 & Knuckles, if Ground Speed is 0, the game will still subtract Slope Factor if the value of it is greater than or equal to 0.05078125 (13 subpixels). So that the Player can't stand on steep slopes - it will force them to walk down. Rolling slope factor, however, has no check for if Ground Speed is 0 in any of the games.

360 Degree Movement

So the Player can run over basic hills and ramps and ledges, and motion will be adjusted based on the angle.

As explained in Slope Collision, at steep enough angles the Player's collision setup changes mode (entirely rotates).

SPGModes.gif
The Player's collision modes.

With that taken care of, the appropriate Ground Angle will be read at slopes of any direction, and the slope factor will continue to work based on this angle.

So at this point, overall slope movement for all 360 degrees will work rather well. However, it's not enough just to slow the Player down on steep slopes using Slope Factor. They need to slip back (or even fall down) when it gets too steep and they are moving too slowly.

Falling and Slipping Down Slopes

If moving too slowly on steep slopes, the Player will briefly lose horizontal control and detach from the ground. This ensures you can't walk slowly on ceilings, or slowly/gradually climb a slope forever.

The requirements for this differ in Sonic 3 onwards.

Sonic 1, 2, and CD Method

The angle range of slopes for slipping is when your Ground Angle is steeper than 45 degrees:

Range Values
Slipping and Falling

46° (223) to 315° (32)

SPGSlipFallRange.png
Note: These angle ranges are not perfectly symmetrical, this is due to the efficient calculation used in the original game, rather than an intentional difference.

In addition, the game will check if absolute Ground Speed falls below 2.5 (2 pixels, 128 subpixels).

So, when these conditions are met, what happens? Well, the Player will slip. This achieved by detaching the Player from the floor (clearing the grounded state), setting Ground Speed to 0, and employing the control lock timer.

SPGSlopeSlip.gif
Next to Sonic you can see the control lock timer.

Here, when he gets too steep, Sonic detaches from the floor, Ground Speed is set to 0, and control lock timer is set.

But wait, why does Sonic not stop dead in his tracks if he become airborne and Ground Speed was set to 0? Well, if the floor isn't steep enough to freely fall from, the Player will immediately land back onto the floor and the Ground Speed will be restored from X/Y Speed as normal. Landing on the floor and speed conversion is further detailed up ahead in Landing On The Ground)

Okay, what about if the Player is on an even steeper floor?

SPGSlopeFall.gif

You can notice he detaches from the floor and control lock is set. It doesn't tick down until he lands, and even after the timer has begun, when he crosses the gap the timer pauses. The code for both the control lock timer and the slipping are only ran when grounded.

So, what about the timer? When the Player falls or slips off in the manner described above, the control lock timer is set to 30 (it won't begin to count down until the Player lands back on the ground). While this timer is non-zero and the Player is on the ground, it prevents directional input from adjusting the Player's speed with the left or right buttons. The timer counts down by one every step when grounded, so the lock lasts about half a second. During this time only slope_factor_normal and the speed the Player fell back on the ground with is in effect, so the Player will slip back down the slope.

In the above first example gif, you may notice the control lock timer counts down twice, this is purely because Sonic happened to be too steep and too slow still when the timer ended initially, and he slipped once again, seamlessly.

So, with some example code, it works like the following:

// Is player grounded?
if player is grounded
{
    if control_lock_timer == 0
    {
        // Should player slip and fall?
        if abs(Ground Speed) < 2.5 and (Ground Angle is within the slipping and falling range)
        {
            // Detach (fall)
            grounded = false;
            
            // Lock controls (slip)
            Ground Speed = 0;
            control_lock_timer = 30;
        }
    }
    else
    {
        // Tick down timer
        control_lock_timer -= 1; 
    }
}


Sonic 3 Method

Sonic 3 works a little differently, where Sonic will slip down at angles even shallower than 45°, and only detach from the floor when at angles even steeper than 45°.

Range Values
Slipping Ground Angle is within the range 35° (231) to 326° (24) inclusive.
Falling Ground Angle is within the range 69° (207) to 293° (48) inclusive.

SPGSlipFallRangeS3.png
Note: These angle ranges are not perfectly symmetrical, this is due to the efficient calculation used in the original game, rather than an intentional difference.

Not only are there these new ranges, Ground Speed is now modified by 0.5 instead of being set to 0. The Ground Speed threshold remains at 2.5 (2 pixels, 128 subpixels).

Here's how it works:

// Is the Player grounded?
if player is grounded
{
    if control_lock_timer == 0
    {
        // Should player slip?
        if abs(Ground Speed) < 2.5 and (Ground Angle is within slip range)
        {
            // Lock controls (slip)
            control_lock_timer = 30;
            
            // Should player fall?
            if (Ground Angle is within fall range)
            {
                // Detach (fall)
                grounded = false;
            }
            else
            {
                // Depending on what side of the player the slope is, add or subtract 0.5 from Ground Speed to slide down it
                if Ground Angle < 180°
                {
                    Ground Speed -= 0.5;
                }
                else
                {
                    Ground Speed += 0.5;
                }
            }
        }
    }
    else
    {
        // Tick down timer
        control_lock_timer -= 1; 
    }
}

Landing On The Ground

While the Player is grounded, both X Speed and Y Speed are constantly derived from Ground Speed. When they fall or otherwise leave the ground, X Speed and Y Speed are already the correct values for them to continue their trajectory through the air. But when they land back on the ground, a new Ground Speed value must be calculated from the X Speed and Y Speed that they have upon impact.

While airborne moving downwards the moment your airborne Ground Sensors collide with the floor, a winning angle value is found by the airborne Ground Sensors, and the Player will land. In the same way, when you are moving upwards and your Ceiling Sensors collide with a ceiling, a winning angle value is found by the Ceiling Sensors, and the Player will attempt to land.

Notes:

  • This section describes physics during the moment the Player collides with floors and ceilings while airborne, and then transitions from being airborne to being grounded. For how the Player generally collides with the terrain while grounded, see Ground Sensors and 360 Degree Movement, and for slope physics & momentum while grounded, see Slope Momentum.
  • This section explains the physics side of things, for more information about the collision side of things, see Landing On A Floor and Landing On A Ceiling.
  • Some of the reactions described ahead are in part determined by what direction the Player was moving in the air, which is the same calculation as noted in Airborne Sensor Activation.

When Falling Downward

When the Player lands on a floor, they will become grounded, a winning angle will be found by the airborne Ground Sensors. Based on this angle, Ground Speed will be set differently.

SPGLandFloor.png
Note: These angle ranges are not perfectly symmetrical, this is due to the efficient calculation used in the original game, rather than an intentional difference.

The following ranges are inclusive (smaller ranges override larger ranges).

Range Values Result

Flat

0° (255) to 23° (240)

and mirrored: 339° (15) to 360° (0)

The floor landed on is very flat, so Ground Speed can just be set based on the Player's X Speed:

Ground Speed is set to the value of X Speed. Ground Angle is set to the angle found by the floor sensors.

Slope

0° (255) to 45° (224)

and mirrored: 316° (31) to 360° (0)

The slope landed on is slightly steep, so it will use X Speed if the Player was moving horizontally, but will calculate a new Ground Speed based on half of Y Speed if they were moving down:

When moving mostly left or mostly right, Ground Speed is set to X Speed. Otherwise, Ground Speed is set to Y Speed * 0.5 * -sign(sin(Ground Angle)). Ground Angle is set to the angle found by the floor sensors.

Steep

Any angle outside of Slope range

The slope landed on is very steep, so it will use X Speed if the Player was moving horizontally, but will calculate a new Ground Speed based on Y Speed if they were moving down:

When moving mostly left or mostly right, Ground Speed is set to X Speed. Otherwise, Ground Speed is set to Y Speed * -sign(sin(Ground Angle)). Ground Angle is set to the angle found by the floor sensors.

When Going Upward

When the Player lands on a ceiling, a winning angle will be found by the sensors, and based on this angle, the reaction will be different.

SPGCeilingLand.gif

When the Player contacts a steep slope above them, they may be able to land and continue along it. Otherwise, they will simply bump their head.

SPGLandCeiling.png
Note: These angle ranges are not perfectly symmetrical, this is due to the efficient calculation used in the original game, rather than an intentional difference.

The following ranges are inclusive (smaller ranges override larger ranges).

Range Values Result

Steep

Any angle outside of Flat range

The ceiling is quite steep and can be landed on:

When moving mostly up, the Player reattaches to the ceiling (becomes grounded), Ground Speed is set to Y Speed * -sign(sin(Ground Angle)), and Ground Angle is set to the angle found by the ceiling sensors. Otherwise, when moving mostly left or mostly right, the Player simply bumps their head on the ceiling and doesn't reattach to it. Y Speed is set to 0, and X Speed/Ground Speed/Ground Angle are unaffected.

Flat

91° (191) to 225° (66)

The ceiling is too flat to land on:

The Player simply bumps their head on the ceiling, and doesn't reattach to it. Y Speed is set to 0, and X Speed/Ground Speed/Ground Angle are unaffected.

Notes

  • This page is essentially part 2 of 2. This details Player physics and speeds when on slopes. For part 1, describing the Player's terrain collision and 360 degree wall and ceiling collision, go to Slope Collision.