Actions

SPG:Game Objects

From Sonic Retro

Notes: Research applies to all four of the Mega Drive games, and Sonic CD. If there are any varying differences between the games, this will be covered below.

Variables

The following variables/constants will be referenced frequently in this section.

//Variables
xpos: The X-coordinate of Sonic's center.
ypos: The Y-coordinate of Sonic's center.
xsp: The speed at which Sonic is moving horizontally.
ysp: The speed at which Sonic is moving vertically.
gsp: The speed at which Sonic is moving on the ground.
slope: The current slope factor (slp) value being used.
ang: Sonic's angle on the ground.
	
//Constants
acc: 0.046875
dec: 0.5
frc: 0.046875 (same as acc)
top: 6
jmp: 6.5 (6 for Knuckles)
slp: 0.125
slprollup: 0.078125
slprolldown: 0.3125
fall: 2.5

Introduction

Objects move in various ways, some simple and some rather complex. It may be enough to simply observe an object to know how it acts, but this isn't the case most of the time where greater depth is required. Additionally, object-player collision doesn't work the same way as Solid Tiles This guide will go over the behaviours, movements and collision of various objects found in the Sonic trilogy.

Hitboxes

Zone layouts are constructed from tiles, and Sonic interacts with those using sensor lines (see Sensors). While this works great for slopes when there's only level tiles to deal with, when Sonic has to interact with multiple moving objects onscreen, a simpler approach is adopted.

Most object sprites use a rectangular hitbox in order to interact with Sonic. Hitboxes in the classic Sonic games are usually non-solid object only areas of collision. They can pass over eachother without pushing eachother away but will trigger a reaction specific to that object.

Of course, not all objects choose to use hit boxes or solid boxes at all and may use bespoke code, and any object with slopes on it specifically will need more complicated collision, we'll be going over a few of these.

Construction

Hitboxes are built using a radius for width and a radius for height. However, just like Sonic's sensors, this also includes the objects origin.

SPGHitBoxRadius.png

So, frustratingly, a hitbox with a width radius of 8 (when defined as 8 in the code) ends up being 17 pixels wide ingame rather than 16. As a result all hitboxes in the entire game will be an odd number in size.

To avoid confusion, both sets of data will be mentioned, otherwise just refer to the sizes shown in the image examples.

Sonic's Hitboxes

In order to interact with these object hitboxes, Sonic needs his own.

SPGHitBoxes.pngSonic's hitbox doesn't appear to actually change while crouched... this might be a tad unfair or seem undesirable, so what's shown is a hitbox similar to that of rolling.

These would all be centred around on Sonic's position, as are those of any object. They do not rotate with Sonic as he runs on walls, however this would be a fine feature to add in a newer framework.

His Hit Box

The smaller purple box will be checking for anything which isn't solid, which can be normal hitboxes for rings, enemies, and hazards (hurt boxes).

As stated, when Sonic and an object's hitboxes touch it causes a reaction, depending on the object. Specifically, objects can have a few different types: non-solid normal ones for collectables like rings, non-solid ones for Badniks (which don't just hurt you but allow you to attack them etc - these will be depicted in the same way as the hitboxes for collectables such as rings for simplicity), non-solid ones that always hurt Sonic, non-solid special ones which use object specific code. They all do different things, however the method they use to come into contact with Sonic in the first place is all the same. Simply put, if they overlap, the object (or Sonic) will react.

Object's solid boxes are handled using Sonic's Solid Box.

His Solid Box

The larger yellow box only looks for solid objects, it's what Sonic will use to walk on them instead of his sensor lines.

Because objects use such different code for collision than with tiles, it can be hard to describe Sonic's boundaries as a true hitbox when it comes to solidity with objects. The original code uses a bizarre system of defining the distance Sonic's x/y position should be from the objects x/y position along both axis, and calculating how far Sonic should stay from the object based on those. It gets the same job done, and isn't worth emulating in that roundabout way.

While Sonic's width and height (shown in yellow above) is the size that it is when defined in-game (and this matches the size of his body width and height radius as defined in Sensors), Sonic will still push against objects with a width of 21, much like with his E & F sensors (however as stated, object collisions do not use Sonic's sensor arrangement). To give an idea to the vertical size of Sonic's wall collision with objects, Sonic will push against an object which is only 2px out from the floor, which wouldn't be the case for Solid Tiles using his sensor lines.

So really, the difference between Sonic's floor and wall collision for objects is ~2px in X or Y. You could imagine it as a second hitbox, over the top of the yellow one shown above, but always 21px wide (2px wider when standing) and 1px smaller on top and bottom, where this new box would only push and the other box would only stand/hit ceilings. This isn't a 1:1 description of how it works, of course, rather a simplification.

So while it isn't quite as simple as it looks, normal AABB collision would suffice.

Quirks With Hitboxes

Because these hitboxes aren't even numbered in size, and because object origins don't lay perfectly centred between pixels (rather they are 1px left and down) most hitboxes will also appear 1px too big on the right side and the bottom side. This is simply how things work in game and for that reason won't be ignored. Sprites like rings are even numbered sizes (such as 16 x 16) so an anomaly like the following can (and does, always) occur.

SPGRingTest.gif

Rings can be collected from one direction sooner than the other, you can try it yourself via debug mode. As long as the sprite of the ring is 4px out from the tiles on each side, you'll experience this inconsistency. A Ring's hitbox is defined as a radius of 6, but this results in a box with a width of 13 rather than 12. Because all sprites like this are an even size, but their hitbox must be odd, the box cannot be perfectly set on the sprite and will be larger to the left and bottom.

This is the case with any object's hitboxes.

The same is true for solid object boxes, so Sonic will push against objects 1px further away when facing leftwards than he will tiles.

General Objects

General objects appear in many zones and games and the code should be the same between them.

Rings

SPGRingHitbox.png

Rings have a hitbox with a width radius of 6 and a height radius of 6, resulting in a 13 x 13 rectangle. (while their sprite is larger, at 16px), so Sonic can get quite close to a ring before a collision occurs and he collects it.

Springboards

Red springboards propel Sonic at a speed of 16, and yellow springboards at a speed of 10. If the springboard faces up or down, the value is either negative or positive, respectively, and ysp is set to it. If the springboard faces left or right, the value is either negative or positive, respectively, and xsp is set to it. Vertical springboards don't affect xsp and likewise horizontal springboards don't affect ysp.

In Sonic 1, springs were simple solid boxes which had the boundaries you'd expect, but after Sonic 2 added diagonal springs the activation area for normal springs changed, and now in Sonic 2 onwards if you walk into a sideways spring slowly you'll realise that it propels you far sooner than you'd expect. This might not be worthwhile emulating.

Diagonal Springboards

There are no diagonal springboards in Sonic the Hedgehog (16-bit). But there are in Sonic 2 (16-bit), 3, K, and CD. Sonic 2, 3, and K work the same way, but Sonic CD is different.

In Sonic 2, 3, and K, a diagonal spring sets both xsp and ysp to the springboard's value, with the appropriate sign. So a red springboard facing up and to the right sets ysp to -16 and xsp to 16. The trouble with this method is that Sonic is technically bounced faster diagonally than horizontally or vertically. This is because they didn't bother to calculate the sine functions.

In Sonic CD, they do however. Conveniently, the absolute sine and cosine of a 45 degree angle are the same, so you only need one value. It comes out to 11.3125 for Red springs and 7.0703125 for Yellow ones.

Horizontal Control Lock

When Sonic bounces away from a horizontal springboard (red or yellow), he cannot brake or otherwise affect his xsp for 16 steps. The engine achieves this by setting the same horizontal control lock as when sliding back down steep inclines (in S3&K, bytes $32-33 in the player object's status table). Why lock the horizontal controls? The player is likely to be pressing in the direction of the springboard as they run into it, and this would cause Sonic to bounce away in his braking animation. Temporarily ignoring input is a quick and elegant solution.

Bumpers

Bumpers such as those in Spring Yard Zone set Sonic's xsp to 7*cosine(p), and ysp to 7*-sine(p), where p is the angle measured from the bumper's centre to Sonic's. This is regardless of Sonic's velocity when he hits the bumper.

SPGBumperHitbox.png

Bumpers have a hitbox with a width radius of 8 and a height radius of 8, resulting in a 17 x 17 rectangle. Other than the hitbox speed repulsion, there is no solidity to bumpers.

Bridges

The bridges in Sonic 1, 2 and 3 are known for their dynamic movement as Sonic moves over them. Bridges are set up with a controller object and an array of log objects which the controller object creates, though this can just be an array of values to represent the segments in most engines now. The controller object contains a few variables: There's the length (in segments) of the bridge, which is usually 12, but it can be longer; there's the index of the segment Sonic is standing on, which starts at 0 for the leftmost segment and ends at length-1.

Depression Amount

The depression amount is the lowest the bridge can go at any given time. This changes depending on the log Sonic is standing on. To get the current maximum depression amount in pixels the bridge controller uses predetermined values for each log.

The values go up in 2's, starting at 2 and continuing to the middle, with the other side being a mirror of the first half. For example, a bridge with length 5 will have the values 2,4,6,4,2 and a bridge with length 6, the values would be 2,4,6,6,4,2. The bridges commonly found in Sonic (12 segments in length) would have the values 2,4,6,8,10,12,12,10,8,6,4,2.

To get the current maximum depression for the bridge, the game uses the value from the log currently being stood on. We'll call the current value MaxDepression.

Calculating Each Log Depression

The ypos of the segments in the bridge depend on the log that Sonic is currently standing on, as so:

SPGBridge.png Sonic is on the 5th segment, we'll call this the CurrentSegment and it's value is 5.

In this example, the depressions would look as follows: 2,4,6,8,10,12,12,10,8,6,4,2 So the current MaxDepression for the bridge will be the 5th log's value, which is 10.

To calculate the position of each log, we calculate how far it is from CurrentSegment relative to the edge it's near. We will call this value LogDistance.

 Segment 0 is 1/5 of the way to CurrentSegment, so it's LogDistance is 1/5 or 0.2.
 Segment 1 is 2/5 of the way to CurrentSegment, so it's LogDistance is 2/5 or 0.4. 
 Segment 4 is 5/5 of the way to CurrentSegment, so it's LogDistance is 5/5 or 1. 


Working from the other side, we use the distance from the end to CurrentSegment, rather than from the start.

 Segment 11 is 1/8 of the way to CurrentSegment, so it's LogDistance is 1/8 or 0.125.
 Segment 6 is 6/8 of the way to CurrentSegment, so it's LogDistance is 6/8 or 0.75.


(Since we've already calculated segment 4 from one direction, there's no need to do it from the other).

We then use LogDistance to calculate it's position:

 LogY = BridgeY + MaxDepression * sine(90 * LogDistance).


Some code to calculate these automatically may go as follows (assumes first segment index starts at 0 in loop for other purposes, but CurrentSegment would start at 1).

 for (i = 0; i < SegmentAmount; i++)
 {
   //get difference of log
   var log_difference = abs((i+1)-CurrentSegment);
   
   //get opposite distance from current log to a side, depending if before or after CurrentSegment
   if (i < CurrentSegment) LogDistance = log_difference / CurrentSegment; else LogDistance = log_difference / ((SegmentAmount - CurrentSegment) + 1);
   
   //get y of log using max depression and log distance (reversed)
   LogY = BridgeY+((MaxDepression) * sine(90 * (1 - LogDistance)));
 }


Meanwhile, all these depression values are multiplied by the sine of the angle in the controller object that counts to 90 when Sonic is standing on top, and down to 0 when Sonic gets off, so the depression will smoothly increase with time when Sonic jumps on to the bridge, and then smoothly decrease when he leaves it.

Breaking Walls

In Sonic 1, 2, 3, & K, the character's absolute xsp must exceed 4.5 in order to break through destructible walls when rolling (except for Knuckles, who busts walls on contact, and doesn't need to be rolled up). xsp is unaffected by the collision, as well.

However, when Knuckles breaks walls in Sonic 3 & Knuckles, though his xsp is unaffected, he doesn't move during the frame in which he hits the wall. The same thing is true when Sonic spindashes through a wall in Sonic 3 & Knuckles.

In Sonic CD, the xsp threshold is removed. Sonic can break through destructible walls by simply jumping near them, or rolling into them at any speed.

Breakable Blocks and Rocks

When Sonic jumps on top of breakable objects, such as the rocks in Hill Top Zone, blocks in Marble Zone, or the tube caps in Chemical Plant Zone, he bounces away with a ysp of -3. xsp is unaffected.

The block produces 4 segments. These segments have a gravity of 0.21875. Their initial x and y speeds are (-2, -2) & (2, -2) for the top two, and (-1, -1) & (1, -1) for the bottom two.

Buttons

SPGButtonHitbox.png

Buttons simply have a solid box (which Sonic can walk on & push against) which is lower than the top of the button when not depressed. When Sonic is standing on it, the subimage changes to depressed and the switch is activated.

End of Level Capsules

Sonic 1 Method

Explosion

For 60 steps, every 8 steps, spawn explosion at capsule position plus random x,y offset (Max horizontal offset of 31 pixels, and according to calculations, vertical is the same). At end of those 60 steps, start with the animals

Animals

Switch to exploded frame. Spawn 8 animals at capsule position -28x, +32y, horizontally separated by 7, with alarms starting from 154 and decreasing by 8 per animal (animals don't jump out until their alarm reaches zero).

For 150 steps, every 8 steps, spawn animal at random x position amongst the existing animal group (but tighter in, not near edges), with their alarm set to 12.

When all animal objects have disappeared, run Got Through message.

Sonic 2 Method

Explosion

An explosion spawns at lock's position, move lock at +8x, -4y. Wait 29 steps.

Animals

8 animals spawn at capsule position -28x, +32y, horizontally separated by 7, with alarms starting from 154 and decreasing by 8 per animal (the animals don't jump out until their alarm reaches zero).

For 180 steps, every 8 steps, an animal will spawn at random x position amongst the existing animal group (but tighter in, not near edges), with their alarm set to 12.

When all animal objects have disappeared, the game will run the 'Got Through' message.

Game Specific Gimmicks

Sonic 1

Badniks

Here the hitboxes and movments of enemies will be detailed.

A yellow box in this section refers to the box the enemy uses to collide, rather than something Sonic can collide with. Sonic will only care about with their main (cyan) hitbox or others (if they have any).

Motobugs

Motobugs move at a speed of 1. Once they touch a wall, they wait for 1 second before starting off in the other direction.

SPGMotobugHitbox.png

Motobugs have a hitbox with a width radius of 20 and a height radius of 16, resulting in a 41 x 33 rectangle.

Choppers

Choppers have a gravity of 0.09375 and bounce with a speed of -7 at the ypos where they spawned.

SPGChopperHitbox.png

Choppers have a hitbox with a width radius of 12 and a height radius of 16, resulting in a 25 x 33 rectangle.

Buzz Bombers

Buzz Bombers move at a speed of 4 (or -4).

SPGBuzzBomberHitbox.png

Buzz Bombers have a hitbox with a width radius of 24 and a height radius of 12, resulting in a 49 x 25 rectangle.

Crabmeats

Crabmeats move at a speed of 0.5 (or -0.5) while walking.

SPGCrabmeatHitbox.png

Crabmeats have a hitbox with a width radius of 16 and a height radius of 16, resulting in a 33 x 33 rectangle.

Projectiles

When shot, Crabmeat's projectiles are given a Y Speed of -4, and an X Speed of either positive or negative 1. They have a gravity of 0.21875.

Green Hill

S Tunnels

The S Tunnels in Green Hill Zone simply keep Sonic rolling at all times. If his speed reaches 0 and he stands up, the game acts as if you have pressed down and he rolls again instantly. Since the S tunnels have no flat ground, Sonic will always roll down it and should never just crouch. However, as part of the function making Sonic roll, if his gsp does happen to be 0, it will set his gsp to 2.

Marble

Spike Traps

When Marble Zone Spike traps fall, their Y Speed increases by 0.4375 each frame. When they reach full length, they spend about 60 frames there. After this they begin to rise by 0.5px per frame, or 1 pixel every 2 frames. The length they can fall varies.

SPGSpikeTrapHitbox.png

They have a solid box at the top (which Sonic can walk on & push against) however the spike area is a damage hit box which will simply hurt Sonic upon contact but doesn't have solidity.

Scrap Brain

Conveyor Belts

A Scrap Brain Zone conveyor belt will simply add the belt speed to Sonics xpos, Sonic's speeds are unaffected.

Sonic 2

Chemical Plant

Spring Ramps

Spring ramps aren't quite as simple as normal springs. Firstly, they have a specific region where they actuate.

SPGSpringRampActuationRegion.png

The ramp will activate if his xpos is within the green region as he stands on it.

When a Spring ramp activates they don't bounce Sonic instantly, instead, Sonic moves down a bit as the animation plays. There are 2 subimages, normal and down, and these both have different collision height arrays as shown below.

SPGSpringRampSolidty.png

On the left is how the solidity appears in-game, on the right is the height array as it is stored, it simply gets scaled by 2 horizontally. The ramps only use this collision data and no hitboxes, and it would be confined to the sprite size (even though it appears to go past it here).

Once activated it plays the down subimage for 4 frames, and Sonic will lower with it but is otherwise unaffected and will keep walking. On the next frame it's back up and Sonic is raised again but still unaffected, on the frame after this Sonic will actually be in the air.

So how fast do they bounce Sonic? Well, that's not perfectly simple either. It will bounce Sonic up with a ysp of -4, and depending on Sonic's xpos position along the ramp it will subtract a second modifier from his ysp. This is all dependant on the positions where Sonic's xpos is right now as he is bounced, not where he was when activated it.

SPGSpringRampPowerSteps.png

From left to right this modifier can be 0, 1, 2, 3 or 4.

So if Sonic happened to be in section 3, his ysp would become -4, minus the modifier of 2, resulting in -6.

His xsp is also affected, if it's absolute value happens to be larger than or equal to 4, the modifier will be added to (or subtracted from) xsp. If Sonic is in section 3, and he has a speed of 5, his speed would become 5+2. This gets capped at 6 in Sonic 2 due to the speed cap still being present in the air.

Spring Caps

The red spring caps that cover the tubes in Chemical Plant Zone work like springboards, but are slightly stronger than a Yellow springboard. They set Sonic's ysp to -10.5 upon collision.

Spinners

The black spinners that impel you forward in Chemical Plant Zone set xsp to 16. They don't seem to slow you down if you're already moving faster than that, though.

Hill Top

Ski Lifts

The ski lifts in Hill Top Zone move with an xsp of 2, and a ysp of 1.

Sonic 3

Carnival Night

Balloons

The balloons in Carnival Night Zone set ysp to -7 when Sonic collides with them, no matter what his angle of collision. xsp is not affected.

SPGBalloonHitbox.png

Balloons have a hitbox with a width radius of 8 and a height radius of 8, resulting in a 17 x 17 rectangle.

Cannons

The cannons in Carnival Night Zone set Sonic's xsp to 16*cosine(p), and ysp to 16*-sine(p), where p is the angle of the cannon.

Sonic and Knuckles

Mushroom Hill

Mushrooms

The mushrooms in Mushroom Hill Zone work just like springboards, only each successive bounce is higher than the last, up to three bounces. The first bounce sets ysp to -6.5, the second, -7.5, and the third, -8.5.

Points

When you hit a Badnik or other point-bearing item (such as Bumpers), a small score notification will fly up out of it. After it spawns at the object's X and Y position, it begins with a Y Speed of -3, and will slow down by 0.09375 each frame. Once it is no longer moving, it will vanish. This will take around 32 frames.