Sunday, March 23, 2014

Walljumping

Walljumping occurs when the player enters a block by just over 2 pixels.  I am going to explain it fully in this description.
First I'm going to begin about talking about how the player moves.  Have you ever wandered what speeds actually meant?  Basically, the game's smallest unit of measurement in speeds is not in pixels, but subpixels.  There are 16 subpixels in one pixel, meaning that there are 256 in each tile of the game.  The player doesn't move relative to pixels, but in fact subpixels.  When you have a speed of 19, this means that you are moving 19 subpixels per frame.

To make this more comprehensible, you can convert everything into subpixels when it comes to the player.  The player's subpixel is not exactly accurate, as it takes up an entire byte.  To make it take up only 16 values (0-15) we must divide it by 16.  To convert from pixels to subpixels, all that we must do is multiply by 16.  This new position is the "combined position" and allows you to check things in units of subpixels rather than random check values.
Hypothetically, let's say that Mario is at position 255.c0 (according to the game)
255 * 16 + c0 (192) / 16 = 4092

Since mario's speed is measuring in subpixels per frame, all that we must do to find his position on the next frame of the game is to add the speed in which we are at presently.  Now, let's just think for a second, and realize that eventually, the game is going to have the player move so many subpixels per frame that he is going to have the capability to skip over a slight section of the block you are hitting.  If you were to get into a position in which you could move over 2 pixels into the block, you could clip the bottom of the block that you are hitting.  What is intended is for you to hit the block, and then immediately be shoved out.

Remember that we are working with subpixels, so 2 pixels is going to be represented as 32 subpixels.
Since we want to go into the block by more than 2 pixels, we will need to be moving 33 subpixels per frame at least, or, in other words, have an x speed of 33 or more.

Keep in mind that you must be in the position in which you can move passed the position of the block by more than 2 pixels, meaning that just getting 33 speed will not do anything.  You must get to the point in which the subpixels will align just perfectly for you to be able to get passed the block by 33 subpixels within one frame, and be able to hit the block before being shoved out.
In this case, I have found a frame where I can in fact pull this off:
This is the point in time where I will be moving and my positions will fall just right so that I can go into the position of the block by 2 pixels.
Mathematical proof:
Position of block: 2285.00
Position of player: 2293.d0 moving with -35 velocity
Block Position in subpixels: 36560
Player Position in subpixels: 36701

Player prediction of position (moving -35 subpixels every frame):
36701, 36666, 36630, 36595, 36560, 36525 <-- Position before I am shoved out of the block
However, if you notice, I come across the exact position of the block on a frame, but I still haven't gone into the block yet, which is when it actually pushes you out.  So, 36525 < 36560 - 32 which means that this is a successful walljump, as my lua script shows.
This means that my position before the block shoves me out should be:
floor(36525 / 16).(36525 % 16 * 16)
which is 2282.d0 (2282.208 without hex conversion)
However, sadly, block pressure is going to slightly push you out as soon as you touch the side of the block, landing your actual position at 2283.e0 (increase of 1.10 pixels).  But, this is still a correct walljump value.

So, that is how a walljump works on a subpixel level, and also how you can predict it.

No comments:

Post a Comment