Actions

Difference between revisions of "SPG:Ring Loss"

From Sonic Retro

m (changed the psuedo code bit to be correct)
m (Link to scattered ring physics behavior)
 
(11 intermediate revisions by 4 users not shown)
Line 1: Line 1:
Note: Research gathered from [[Sonic the Hedgehog (16-bit)]], but it is highly likely that it holds true for [[Sonic CD]], [[Sonic 2 (16-bit)]], [[Sonic 3]], and [[Sonic & Knuckles]].
+
{{SPGPages}}
 
+
'''Notes:'''
 +
*''The research applies to all four of the [[Sega Mega Drive]] games and [[Sonic CD]].''
 +
*''For the behaviour & movement of scattered Ring objects themselves, see [[SPG:Game_Objects#Scattered_Rings|Game Objects]].''
 
==Ring Limit==
 
==Ring Limit==
 
+
When the Player gets hit, the number of [[rings]] they are carrying scatter away, unless they are carrying more than 32, in which case any rings over 32 are ignored. The Player is therefore no safer carrying 100 rings than 32.
When [[Sonic]] gets hit, the number of [[rings]] he is carrying scatter away, unless he is carrying more than 32, in which case any rings over 32 are ignored. Sonic is therefore no safer carrying 100 rings than 32.
 
  
 
==Ring Distribution==
 
==Ring Distribution==
 
+
The rings that scatter away from the Player are distributed in a specific pattern of 2 concentric circles, each containing a maximum of 16 rings.  The rings in the first circle move outward faster than the rings in the second.   
The rings that scatter away from Sonic are distributed in a specific pattern of 2 concentric circles, each containing a maximum of 16 rings.  The rings in the first circle move outward faster than the rings in the second.  Here is a formula for creating the rings, which can be converted into the programming language of your choice:
+
Here is example code for creating the rings, which can be converted into the programming language of your choice:
 
+
<syntaxhighlight>// Variables and Constants
  {
+
var ring_counter = 0;
  let t = 0
+
var ring_starting_angle = 101.25° (184) ($B8);
  let angle = 101.25 ; assuming 0=right, 90=up, 180=left, 270=down
+
var ring_angle = ring_starting_angle;
  let n = false
+
var ring_flip = false;
  let speed = 4
+
var ring_speed = 4;
 
    
 
    
  while t is less than the number of rings max 32
+
// Perform loop while the ring counter is less than number of lost rings
 +
while ring_counter < number of rings (max 32)
 +
{
 +
    // Create the ring
 +
    create a bouncing ring object at the Player's X and Y Position;
 +
    ring's X Speed = cosine(ring_angle) * ring_speed;
 +
    ring's Y Speed = -sine(ring_angle) * ring_speed;
 +
   
 +
    // Every ring created will moving be at the same angle as the other in the current pair, but flipped the other side of the circle
 +
    if ring_flip == true
 
     {
 
     {
    create a bouncing ring object
+
        ring's X Speed = ring's X Speed * -1;  // Reverse ring's X Speed
    set the ring's vertical speed to -sine(angle)*speed
+
        ring_angle += 22.5° (16) ($10); // We increment angle on every other ring which makes 2 even rings either side
    set the ring's horizontal speed to cosine(angle)*speed
 
    if n is true
 
      {
 
      multiply the ring's horizontal speed by -1
 
      increase angle by 22.5
 
      }
 
    let n = not n ; if n is false, n becomes true and vice versa
 
    increase t by 1
 
    if t = 16
 
      {
 
      let speed = 2 ; we're on the second circle now, so decrease the speed
 
      let angle = 101.25 ; and reset the angle
 
      }
 
 
     }
 
     }
  }
+
   
 
+
    // Toggle flip
So, the first 16 rings move at a velocity of 4 pixels per step, and the second 16 move at half that rate, or 2 pixels per step.
+
    ring_flip = !ring_flip;  // If flip is false, flip becomes true and vice versa
 
+
   
==Ring Gravity==
+
    // Increment counter
 
+
    ring_counter += 1;
Rings do not heed the same gravity constant as Sonic does.  Instead, their gravity is a force of 0.09375.  So, this value is added to the rings' vertical speed every step.
+
   
 
+
    // If we are halfway, start second "circle" of rings with lower speed
==Ring Bounce==
+
    if ring_counter == 16
 
+
    {
When the scattered rings hit the ground, their vertical speed is multiplied by a factor of -0.75.  This has the effect of reversing their vertical motion, as well as slowing it somewhat.  This calculation is performed after the addition of the gravity.  Their horizontal speed is unaffected by bouncing.
+
        ring_speed = 2;
 
+
        ring_angle = ring_starting_angle; // Reset the angle
When the rings bounce off the floor, they do so so imprecisely, it is almost embarrassing. But this is really not noticed during normal play, and was perhaps necessary to avoid too much slowdown.  It looks to me like they don't check to see if they are colliding with the ground every step, so they sometimes pass well into the ground before deciding to bounce away.  This is something not really worth emulating.
+
    }
 
+
}</syntaxhighlight>
But there are further limitations on bouncing rings, probably also in place to avoid processor load.  They are totally unaffected by walls, and are only concerned with vertical surfaces.  Moreover, they only check to see if they are colliding with a solid when they are moving downward (i.e. their vertical speed is positive).  Thus they can also fly up through ceilings.  This can actually become a bother to Sonic if he is struck in a small corridor, as most of his rings are lost in the ceiling and don't fall back down to be regathered.
+
So, the first 16 rings move at a speed of 4 pixels per frame, and the second 16 move at half that rate, or 2 pixels per frame.
 
 
Personally, if I were using a system with more power than the Genesis/Mega Drive, I would make the rings check for horizontal collisions.  If they collide, then they should multiply their horizontal speed by a factor of -0.25.  I would also check for ceilings, by asking in their vertical collision check whether they are moving up or down.  If they are moving down, they should bounce as normal, but if they are moving up, they should set their vertical speed to 0.  This is kinder to the player, for most of the rings do not get lost due to system limitations.
 
 
 
==Ring Lifespan==
 
 
 
All scattered rings are destroyed after 256 steps if they have not been regathered.  Also, if they leave the horizontal view boundaries, they are destroyed.  Again, on a more powerful system, you may choose not to include this feature.
 
  
 
==Regathering Rings==
 
==Regathering Rings==
 
+
''64'' frames must have passed since the Player was hit before they can regather any rings, scattered or otherwise.
64 steps must have passed since Sonic was hit before he can regather any rings, scattered or otherwise.
 
  
 
==Invulnerability==
 
==Invulnerability==
 +
The Player remains invulnerable for a short time after being hit. This invulnerability lasts while the Player is flying back from the blow, and then ''120'' frames more after they land and recover movement.  During those ''120'' frames, they flash on and off, spending ''4'' frames on and ''4'' frames off.
  
Sonic remains invulnerable for a short time after being hit.  This invulnerability lasts while Sonic is flying back from the blow, and then 120 steps more after he recovers movement.  During those 120 steps, he flashes on and off, spending 4 steps on and 4 steps off.
+
While in this state, the Player can not collect level rings until less than ''90'' invulnerability frames remain.
 
 
While in this state, Sonic can not collect level rings until less than 90 invulnerability steps remain.
 
 
 
==Ring Animations==
 
 
 
Fixed rings have 4 frames of animation, and spend 8 steps showing each frame before moving to the next.  Scattered rings are more complicated, in that they have a much faster animation speed when they are created, but this slows down over their lifespan.  They begin only showing each frame for about 2 steps, and wind up at the end slowing to a crawl, showing each frame for 16 steps or more.  I do not know the precise values yet.  Scattered rings are created showing their initial frame of animation, which is the ring shown face on.
 
  
 
==Ring Depth==
 
==Ring Depth==
 
+
All rings, scattered or fixed, have a higher depth than the Player, i.e. behind them.  But they have a lower depth, i.e. in front of them, when they turn into sparkles.
All rings, scattered or fixed, have a higher depth than Sonic, i.e. behind him.  But they have a lower depth, i.e. in front of him, when they turn into sparkles.
 
  
 
[[Category:Sonic Physics Guide|Ring Loss]]
 
[[Category:Sonic Physics Guide|Ring Loss]]

Latest revision as of 06:05, 26 June 2023

Sonic Physics Guide
Collision
Physics
Gameplay
Presentation
Special

Notes:

Ring Limit

When the Player gets hit, the number of rings they are carrying scatter away, unless they are carrying more than 32, in which case any rings over 32 are ignored. The Player is therefore no safer carrying 100 rings than 32.

Ring Distribution

The rings that scatter away from the Player are distributed in a specific pattern of 2 concentric circles, each containing a maximum of 16 rings. The rings in the first circle move outward faster than the rings in the second. Here is example code for creating the rings, which can be converted into the programming language of your choice:

// Variables and Constants
var ring_counter = 0;
var ring_starting_angle = 101.25° (184) ($B8);
var ring_angle = ring_starting_angle; 
var ring_flip = false;
var ring_speed = 4;
  
// Perform loop while the ring counter is less than number of lost rings
while ring_counter < number of rings (max 32)
{
    // Create the ring
    create a bouncing ring object at the Player's X and Y Position;
    ring's X Speed = cosine(ring_angle) * ring_speed;
    ring's Y Speed = -sine(ring_angle) * ring_speed;
     
    // Every ring created will moving be at the same angle as the other in the current pair, but flipped the other side of the circle
    if ring_flip == true
    {
        ring's X Speed = ring's X Speed * -1;  // Reverse ring's X Speed
        ring_angle += 22.5° (16) ($10);  // We increment angle on every other ring which makes 2 even rings either side
    }
    
    // Toggle flip
    ring_flip = !ring_flip;  // If flip is false, flip becomes true and vice versa
    
    // Increment counter
    ring_counter += 1;
    
    // If we are halfway, start second "circle" of rings with lower speed
    if ring_counter == 16
    {
        ring_speed = 2;
        ring_angle = ring_starting_angle;  // Reset the angle
    }
}

So, the first 16 rings move at a speed of 4 pixels per frame, and the second 16 move at half that rate, or 2 pixels per frame.

Regathering Rings

64 frames must have passed since the Player was hit before they can regather any rings, scattered or otherwise.

Invulnerability

The Player remains invulnerable for a short time after being hit. This invulnerability lasts while the Player is flying back from the blow, and then 120 frames more after they land and recover movement. During those 120 frames, they flash on and off, spending 4 frames on and 4 frames off.

While in this state, the Player can not collect level rings until less than 90 invulnerability frames remain.

Ring Depth

All rings, scattered or fixed, have a higher depth than the Player, i.e. behind them. But they have a lower depth, i.e. in front of them, when they turn into sparkles.