Note: all examples in this post assume you have already loaded Phaser in a browser session or development environment.
Phaser Basics: Part 1 (Sprites and Groups)
Phaser Basics: Part 2 (Input and Arcade Physics)
In the last post, we worked toward making a top-down game through looking at input and the use of physics functionality like velocity. However, what made it a top-down game, other than me calling it that, was in how we perceived it. Because many of the examples used the arrow keys and had equal movement in all four directions, we perceive this to be top-down.
However, the use of “top-down” merely implies that we, as players, as looking at the objects we are moving from above them, looking from the ‘top’ down to the object themselves. It has nothing to do with the mechanics themselves for the most part and is labeled merely from the visual representation of the game world.
The difference between top-down and platformers (hint: perspective)
In moving toward a platformer in the traditional sense of a side-scroller, we need to shift how we perceive the game space. Instead of moving in all four directions, we need to transition toward thinking about moving either left or right along the horizontal axis.
Movements to match forms
Like with our top-down examples, we also need to adjust our object movement accordingly. Instead of moving in all four directions, we need to limit it to only two (initially). We also need more sprites, too. As we move, we need some visual contrast to show that, yes, some horizontal movement is going on in our example.[gist https://gist.github.com/videlais/d57115c6797f68aeb04e /]
In the above example, we combine most of the concepts from the previous session. We are using the physics system, moving the sprite using its velocity, and changing the background color, too. Something we aren’t using yet, but will be shortly, is collisions.
Similar to our very first example of adding text to the screen using game.add.text, we can also give the player information through having text appear along with our other objects. While we are moving objects, for example, other information could be displayed to the player.
Giving the player a heads-up (display)
In game design terms, a “heads-up display” (HUD) is some visually displayed information. In games like Doom, this is the lower-third of the screen and holds the ammo and health. In games like Super Mario Bros., this is text displaying the coin count and the time left to complete the level. All displayed using text on the screen.[gist https://gist.github.com/videlais/b7602dd4500aa63da034 /]
In the above, we are adding an extra text object to our growing list. Displaying “Coins:” in yellow, we are storing a reference (HUD) and adding to the stage group within the game space.
Now that we have a HUD (called HUD), we need to use it for something. Building on our existing code, we can update the content of the HUD to be, as an example, the x-position of ‘sprite’ as it moves.[gist https://gist.github.com/videlais/bb0d7e11dd7967b45ad1 /]
Now that we are looking at a platformer, it is time to revisit our physics system from the previous post. In addition to our use of velocity, we want something to force objects down: gravity. As an active, constant velocity, this will ‘pull’ our objects toward one direction or another.
The gravity of the situation
While we could use an assigned constant gravity as part of our velocity within our update loop (by adjusting the velocity value directly), we can also set gravity using that specific attribute: gravity. Each body in Arcade physics can have their own gravity, or we can set it game-wide using game.physics.arcade.gravity.
Then, by adding another button check, we can make an object go ‘up’ on the screen by using a negative velocity for its y position. When we let go of the button, the object will ‘drift’ down as gravity is applied to it.[gist https://gist.github.com/videlais/991fee1ed341570e2d22 /]
Note: While we would normally use immovable for objects, we are turning off moves in the above example to prevent ‘sprite’ and ‘floor’ from sticking together and exchanging forces. This is also why we are turning off the gravity for ‘floor’, too. We don’t want the floor to float away!
Jumping: a matter of velocity and timing
Building towards a more complete project, you may notice a problem in the previous example: as long as we were holding the UP arrow key, our object kept traveling up on the screen. Unless our object has a jetpack, this doesn’t quite make sense. Most objects ‘jump’ by quickly moving up and then floating down. They don’t stay up.
To fix that issue, we need to cover something else: timing.
Within Phaser, and most game frameworks in general, there is some matter of timing used. For functionality like gravity and velocity, the timing of the moves are just as important as their directionality. Within Phaser, we access this using game.time.
As a last part, we also want ‘jumping’ to happen only when the object is on (colliding with) the ‘floor’. Yes, some platformer games have some type of double-jump mechanic, but that first jump doesn’t happen in mid-air. It always starts on the ground or floor first.
For this, we use one of two additional functions of body: onFloor. (onWall is the other one.)
If we want to know if some object is touching the floor (specifically either a tile or the world bounds), we can test for that. By combining some timing with this test, we can make sure ‘jumping’ only happens when the conditions of the button being pressed AND it is less than some amount of time AND the object is touching a floor are met. Then and only then do we allow an object to ‘jump’.[gist https://gist.github.com/videlais/28daa388615fd5380541 /]