Difference between revisions of "SPG:Player 2"
From Sonic Retro
m (→Landing) |
(Extra info & fixed headers) |
||
(3 intermediate revisions by the same user not shown) | |||
Line 10: | Line 10: | ||
==Player 2 CPU== | ==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=== | ===State Lists=== | ||
Line 32: | Line 32: | ||
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. | 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=== | ===CPU Following State=== | ||
Before anything else happens, if Player 2 currently has an active [[SPG:Running#Control_Lock|control lock]] and their '''''Ground Speed''''' is ''0'', they are most likely stuck on a slope and they will enter their [[SPG:Player_2#CPU_Spindash_State|CPU Spindash state]]. This state will be explained up ahead. Otherwise, Player 2 will continue onto [[SPG:Player_2#CPU Following State|CPU following]]. | Before anything else happens, if Player 2 currently has an active [[SPG:Running#Control_Lock|control lock]] and their '''''Ground Speed''''' is ''0'', they are most likely stuck on a slope and they will enter their [[SPG:Player_2#CPU_Spindash_State|CPU Spindash state]]. This state will be explained up ahead. Otherwise, Player 2 will continue onto [[SPG:Player_2#CPU Following State|CPU following]]. | ||
− | In the CPU Following state, Player 2 will decide upon their CPU controller inputs to adequately follow Player 1 | + | 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 [[SPG:Player_2#Normal Movement|normal movement]] entirely and move onto [[SPG:Player_2#Jumping|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==== | ====Normal Movement==== | ||
− | In Sonic 2, normal movement will begin with | + | 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===== | =====Walking===== | ||
Line 75: | Line 77: | ||
|} | |} | ||
− | =====Actions===== | + | Next are the actions and checks. |
− | If Player 2 is in the air, and they are jumping, they will hold down the {{A}}{{B}}{{C}} buttons on their CPU controller, and then exit the CPU following code for that frame. Otherwise, they will continue to check for more actions. | + | |
+ | =====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 [[SPG:Player_2#Jumping|jumping]] will not occur. | ||
+ | |||
+ | {| class="prettytable" style="width: auto;" | ||
+ | !1: Continuing A Jump | ||
+ | |- | ||
+ | | | ||
+ | If Player 2 is in the air, and they are jumping, they will hold down the {{A}}{{B}}{{C}} 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 | + | If the CPU following code has not been exited, it will move ahead onto the [[SPG:Player_2#Jumping|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=== | ===CPU Spindash State=== | ||
Line 114: | Line 136: | ||
===Tails=== | ===Tails=== | ||
− | In the case of Tails, when they respawn they'll begin flying back in. | + | 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 <code>Player 1's '''''Y Position''''' - 192</code>. 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==== | |
− | ====Horizontal==== | + | 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'''''. |
− | When flying in, Tails will decide how much to move their '''''X Position''''' by based on the difference in '''''X Position''''' and Player 1's '''''X Speed'''''. | ||
<syntaxhighlight>x_difference = Player 2's X Position - target_x; | <syntaxhighlight>x_difference = Player 2's X Position - target_x; | ||
Line 125: | Line 148: | ||
Tails will face whichever direction '''target_x''' is in, and will move towards '''target_x''' by a distance of <code>minimum(x_to_move, absolute(x_difference))</code> in that direction each frame. | Tails will face whichever direction '''target_x''' is in, and will move towards '''target_x''' by a distance of <code>minimum(x_to_move, absolute(x_difference))</code> in that direction each frame. | ||
− | ====Vertical==== | + | ====Vertical Movement==== |
− | Vertically, | + | 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==== | ====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 to'''target_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. | ||
[[Category:Sonic Physics Guide|Player 2]] | [[Category:Sonic Physics Guide|Player 2]] |
Latest revision as of 13:48, 5 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.
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.
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.
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 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 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 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 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.