Actions

SPG:Player 2

From Sonic Retro

Sonic Physics Guide
Collision
Physics
Gameplay
Presentation
Special

Notes:

Introduction

Starting with Sonic 2, a second player can follow you around the stage. At first glance it may seem like they simply copy your inputs, but there is a lot more nuance to the following Player's (Player 2's) actions.

Player 2 Control

By default, Player 2 is CPU controlled; however every time the Player 2 controller detects input, CPU control will be disabled for 10 seconds.

Player 2 CPU

While the Player 2 is CPU controlled and is following Player 1, they access various bits of information about Player 1's state from 16 frames in the past. How does it do this? Well, Players keep lists of their actions and states each frame.

State Lists

The information lists stored is as follows:

Position List

The X/Y Position of the Player.

States List

The grounded state, pushing state, jumping state and direction the player is facing.

Control List

The complete controller inputs being used.

These lists are added to each frame by the Player. Each list is 32 entries long and therefore retains information from the last 32 frames.

Player 2 reads all the data from the entry 16 frames into the past. From this point on this guide, when Player 2 uses this information it will be labelled as target_inputs, target_x, target_y, or target_grounded, etc. These will be in reference to Player 1's state 16 frames in the past that was read from these lists.

CPU Inputs

Firstly, Player 2 will adopt the target_inputs found from Player 1's control list as their CPU inputs. Some of these will be modified up ahead, but if left unchanged, this means Player 2 will copy Player 1 exactly, with a 16 frame delay.

CPU Following State

Before anything else happens, if Player 2 currently has an active control lock and their Ground Speed is 0, they are most likely stuck on a slope and they will enter their CPU Spindash state. This state will be explained up ahead. Otherwise, Player 2 will continue onto CPU following.

In the CPU Following state, Player 2 will decide upon how to modify their CPU controller inputs to adequately follow Player 1.

Firstly, the game checks if Player 2 is stuck. If Player 2 is pushing and target_pushing is not true, this likely means Player 2 is stuck against a wall or object. If this is the case, Player 2 will skip normal movement entirely and move onto jumping. Otherwise, they will continue onto normal movement. Jumping will occur after normal movement if the game doesn't exit CPU following code.

Normal Movement

In Sonic 2, normal movement is were Player 2 moves left or right to follow Player 1, and continues actions & performs checks. This will begin with walking towards Player 1.

Note: In Sonic 3 onwards, if Player 1's absolute Ground Speed is less than 4 and they are not standing on an object, 32 is subtracted from target_x. This allows Player 2 to stand a little behind Player 1.

Walking

Player 2 will then compare their X Position to target_x.

Player 2's X Position is larger than target_x

Here, Player 2 is to the right of Player 1 and will want to move left.

If the absolute distance between Player 2's X Position and target_x is larger than 16 (48 in Sonic 3), Player 2 will begin to move left. They do this by holding Left on their CPU controller, releasing Right, and turning to face left.

Also, Player 2's X Position is manipulated under certain conditions. If Player 2's Ground Speed is not 0, and they are facing left, and they are not pushing, 1 will be subtracted from their X Position, forcefully pulling them towards Player 1.

Player 2's X Position is less than target_x

Here, Player 2 is to the left of Player 1 and will want to move right.

Similarly, if the absolute distance between Player 2's X Position and target_x is larger than 16 (48 in Sonic 3), Player 2 will begin to move right. They do this by holding Right on their CPU controller, releasing Left, and turning to face right.

Also similarly, Player 2's X Position is again manipulated under certain conditions. If Player 2's Ground Speed is not 0, and they are facing right, and they are not pushing, 1 will be added to their X Position, forcefully pulling them towards Player 1.

If Player 2's X Position is equal to target_x

Here, Player 2 doesn't need to move anywhere. Player 2 will turn to face the same way as the target_direction (the way Player 1 was facing).

Next are the actions and checks.

Actions & Checks

Here the game will check various conditions and ensure Player 2 continues actions such as while jumping. If the CPU following code is exited for the current frame after any of these checks, this means that any further checks and jumping will not occur.

1: Continuing A Jump

If Player 2 is in the air, and they are jumping, they will hold down the ABC buttons on their CPU controller, and then exit the CPU following code for that frame. Otherwise, the game will continue to the next checks.

2: Too far away from Player 1

If the absolute distance between Player 2's X Position and target_x is larger than 64, Player 2 will exit the CPU following code for that frame. Otherwise, they will continue to check for more actions. Otherwise, the game will continue to the next checks.

3: Too far below Player 1

If target_y is equal to or greater than Player 2's Y Position, Player 1 is below Player 2 and it will exit the CPU following code for that frame. Otherwise, if the target_y is less than 32 pixels above Player 2's Y Position, Player 1 is less than 32 pixels above Player 2 and it will exit the CPU following code for that frame.

Here, the code is only not exited if Player 1 is more than 32 pixels above Player 2.

If the CPU following code has not been exited, it will move ahead onto the jumping.

Jumping

Here the game will allow Player 2 to jump even when Player 1 hasn't.

Player 2 simply attempts to perform a jump once every 64 frames (checked on a global timer). When that occurs, if they aren't crouching, they will press and hold the jump buttons on their CPU controller inputs, and then exit the CPU following code for that frame.

CPU Spindash State

When in the CPU Spindash state, a few checks are performed.

Firstly, if control lock is active, the game will exit the CPU Spindash code for that frame, but will check again the next frame.

Crouching

Before the Player 2 can Spindash, they'll try to crouch.

Firstly, they'll check if their Ground Speed is 0. If it isn't, the game will exit the CPU Spindashing code for that frame.

They'll turn to face Player 1.

Then they will press and hold down the Down button on their CPU controller in order to crouch.

Meanwhile, the game is checking if they are finally in their ducking sprite. If they are, they will tap the ABC buttons on their CPU controller to initiate the Spindash. However, at the same time every 128 frames (checked on a global timer) the game will check if Player 2 isn't yet crouching. If they are not, the game will cancel the CPU Spindash state entirely and set Player 2's state to the CPU Following state.

Spindash

Once Player 2 begins Spindashing, they will they will tap the ABC buttons on their CPU controller every 32 frames (checked on a global timer).

Meanwhile, every 128 frames (checked on a global timer) the game will release the ABC buttons and down button on their CPU controller, releasing the Spindash. This will also switch the state back to CPU Following.

Respawning

Player 2 will Respawn if they are offscreen for 300 frames.

Tails

In the case of Tails, when they respawn they'll begin flying back in.

Upon respawning, Tails' X Position will be set to Player 1's X Position, and his Y Position will be set to Player 1's Y Position - 192. Also, Tails' target_x and target_y will be set to Player 1's current positions (for that frame only, from here on it uses the delayed values).

Horizontal Movement

When flying in, Tails will decide how much to move their X Position by based on the difference in X Position to target_x, and Player 1's X Speed.

x_difference = Player 2's X Position - target_x;
x_to_move = minimum(12, absolute(x_difference) >> 4) + absolute(Player 1's X Speed); // ">> 4" here is equivalent to dividing by 16, floored

Tails will face whichever direction target_x is in, and will move towards target_x by a distance of minimum(x_to_move, absolute(x_difference)) in that direction each frame.

Vertical Movement

Vertically, Tails will move up or down (modifying Y Position rather than using speeds) by 1 pixel per frame until they reach Player 1's Y Position.

Landing

Player 2 will land when close enough to Sonic, when their X Position is equal to target_x and their Y Position is equal totarget_y. In addition, target_grounded needs to be true.

In Sonic 3, the game also makes sure that Player 1 isn't in their dying state.