Saturday, April 19, 2014

Simulating the Player's Speed

The player's speed has a weird system in general when it comes to things like accelerating and how it works after modifying it.  I decided to look into it because of the confusion it was causing me.

The speed of the player follows a table in the game which, frankly, makes no sense... until now.  Basically, if you are first looking at an acceleration table, you would expect for there to be some sort of speed list of the player to follow, but there's not.  Instead, it happens to be a table to change the value that changes the speed.

Say you wanted to just hold right (and Y) from speed 0 on the ground.  You would come across this strange speed pattern in which looks like it can be derived from a formula:
[0, 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 18, 19, 21, 22, 24, 25, 27, 28, 30, 31, 33, 34, 36]
I'll stop there because I want to explain how the speed initially accelerates.
This pattern looks like the formula floor(1.5 * frame).  However, if you were to, say, release right for one frame (I'll release right on speed 6) you would get something that clearly did not follow this.
[0, 1, 3, 4, 6, 5, 6, 8, 9, 11, 12, 14, 15, 17, 18, 20, 21, 23, 24, 26, 27, 29, 30, 32, 33, 35, 36]

This means that the speed oscillation cannot be represented by a formula.  What is actually happening here is that the game is remembering the last increase in speeds.  This increase cycles between 2 and 1 whenever you hold left or right.  If you hold right from speed 0, it begins at 2, and if you hold left at speed 0, it begins at 1 (which it would subtract instead of add).  If you release your direction (releasing the direction you are holding causes the speed to decrease by 1), the cycle does not go to its opposite value.  Instead, it remembers it, so that when you hold right (or left again), it will continue the pattern it left off with.
Notice that we went from speed 4 to speed 6.  This increase in speeds (which I'll call 's') is 2.  On the next frame that I hold right, it will increase by 1, and then when I do again, it will increase by 2, etc.  So, if I were to not hold right until the speed reached for example, 3, it would increase by 1, and then 2 (3, 4, 6, following its original speeds again), etc.

If you turn around but your direction is opposite your speed, your speed will decrease by 5 (assuming your speed is positive).  So, turning around at speed 9 would drop my speed to 4.
There are two main exceptions to this oscillation of speed using a last value to remember: speed capping and if your speed went back to 0/went the opposite direction.  If my speed were positive and it became negative or went back to 0, then the pattern would be scrapped and start again (ie waiting with an increase that would be 2 until your speed reaches 0 will make it instead increase by the default 1).

The most complex and tricky pattern to replicate is speed capping.  Capping takes place at a maximum speed (37 if running, 49 if sprinting).  If you view the game's ram, you will notice a very similar pattern.  With 37 speed, this pattern of capping is 37, 36, 35, 36, 35, 37, 36, 35, 36, 35, 37...
A pattern like this does not have a set formula or increase, but instead a set of rules:

--> If your speed is exactly the capped speed, 's' will become 1, and the new speed will always be one before the capped speed on the next frame
--> If your speed is going to be greater than the capped speed in reference to s on the next frame, your speed will instead decrease by the inverse of s, and s will become its inverse
--> If your speed is exactly equal to the capped speed - 1, the next speed you will achieve is the capped speed - 2

With these rules, you can achieve the exact pattern of speeds that the game follows.
Note that these speeds are assumed that you are on land, and either have exactly 0 for a p meter (for running) or exactly 112 (for sprinting).

No comments:

Post a Comment