Quantcast
Channel: GameDev Academy
Viewing all articles
Browse latest Browse all 1620

Make a HTML5 Platformer with Phaser

$
0
0

Introduction

There are dozens of HTML5 game frameworks available out there. However, if you are looking for a free, open source, and actively maintained framework, the list quickly narrows down to just a handful of them. And a lot of people consider Phaser to be the best one.

This tutorial will show you how to make the beginning of a 2D platfromer game in HTML5 using the Phaser framework. This tutorial comes from the beginning of the ebook Discover Phaser.

Grab the Entire Ebook for Much, Much More

Discover Phaser

Empty Game

Let’s start by creating an empty game. By the end of this part, we will have this:

HTML5 Phaser tutorial

Don’t worry, it will quickly become more interesting.

Set Up

First we need to create a new directory called “first-game”, where we should add:

  • phaser.min.js, the Phaser framework.
  • main.js, that will contain the game’s code. For now it’s just an empty file.
  • index.html, that will display the game. We can use the same index file that we made in the previous chapter.
  • assets/, a directory that contains all the images and sounds. The assets can be downloaded here

HTML5 Phaser tutorial

Code the Main File

The Javascript code for any new Phaser project is basically always going to be the same:

  1. Create the states. Remember that a state is a scene of a game, like a loading scene, a menu, etc.
  2. Initialise Phaser. That’s where we define the size of our game among other things.
  3. Tell Phaser what the states of our game are.
  4. And start one of the states, to actually start the game.

These 4 steps are explained below in detail.

First, we create the states. For now we will have only one, that will include 3 of the default Phaser functions:

// We create our only state, called 'mainState'
var mainState = {

    // We define the 3 default Phaser functions

    preload: function() {
        // This function will be executed at the beginning
           // That's where we load the game's assets
    },

    create: function() { 
        // This function is called after the preload function
        // Here we set up the game, display sprites, etc.
    },

    update: function() {
        // This function is called 60 times per second 
        // It contains the game's logic
    },

    // And here we will later add some of our own functions
};

The preload, create and update functions are key to any Phaser project, so make sure to read the comments above to understand what they do. We will spend most of our time in these 3 functions to create our game.

HTML5 Phaser tutorial

Then, we initialise Phaser with Phaser.Game.

Phaser.Game(gameWidth, gameHeight, renderer, htmlElement)
- gameWidth: width of the game in pixels
- gameHeight: height of the game in pixels
- renderer: how to render the game, I recommend using Phaser.AUTO that will automatically choose the best option between webGL and canvas
- htmlElement: the ID of the HTML element where the game will be displayed

For our game, we add this below the previous code:

// Create a 500px by 340px game in the 'gameDiv' element of the index.html
var game = new Phaser.Game(500, 340, Phaser.AUTO, 'gameDiv');

Next, we tell Phaser to add our only state:

// Add the 'mainState' to Phaser, and call it 'main'
game.state.add('main', mainState);

And finally, we start our ‘main’ state:

game.state.start('main');

Our empty project is now done. But let’s add a couple of things in it that are going to be useful.

Background Color

By default, the background color of the game is black. We can easily change that by adding this line of code in the create function:

game.stage.backgroundColor = '#3498db';

The #3498db is the hexadecimal code for a blue color.

Physics Engine

One of the great features of Phaser is that it has 3 physics engines included. A physics engine is what will manage the collisions and movements of all the objects in the game.

The 3 engines available are:

  • P2. It’s a full featured physics system that lets us build games with complex collisions, like Angry Birds.
  • Ninja. It’s less powerful than P2, but still has some interesting features to handle tilemaps and slopes.
  • Arcade. It’s the most basic system that only deals with rectangle collisions (called AABB), but it also has the best performance.

Which one is the best? It really depends on what type of game we want to build. In our case we will use Arcade physics, and to tell that to Phaser we just need this line of code in the create function:

game.physics.startSystem(Phaser.Physics.ARCADE);

Conclusion

Once you put all of the Javascript code in the main.js file, you can test the game by using a local webserver.

If you see an empty blue screen, it means that everything is working properly.

Add the Player

The first interesting thing we are going to add to the game is the player, and a way to control it. To do so, we will make some changes to the main.js file.

HTML5 Phaser tutorial

Load the Player

In Phaser, every time we want to use an asset (image, sound, etc.) we first need to load it. For an image, we can do that with the game.load.image function.

game.load.image(imageName, imagePath)
- imageName: the new name that will be used to reference the image
- imagePath: the path to the image

To load the player sprite, we add this in the preload function:

game.load.image('player', 'assets/player.png');

Display the Player

Once the sprite is loaded, we can display it on the screen with game.add.sprite.

game.add.sprite(positionX, positionY, imageName)
- positionX: horizontal position of the sprite
- positionY: vertical position of the sprite
- imageName: the name of the image, as defined in the preload function

Note that if we add a sprite at the 0, 0 position, it will be displayed in the top left corner of the game.

To add the sprite at the center of the screen we could write this in the create function:

// Create a local variable
var player = game.add.sprite(250, 170, 'player');

However, since we want to be able to use the player everywhere in our state, we need to use the this keyword:

// Create a state variable
this.player = game.add.sprite(250, 170, 'player');

And we can do even better by using some predefined variables for the x and y positions:

this.player = game.add.sprite(game.world.centerX, game.world.centerY, 'player');

That’s the line we should actually add in the create function.

Anchor Point

If you test the game, you might notice that the player is not exactly centered. That’s because the x and y we set in game.add.sprite is the position of the top left corner of the sprite, also called the anchor point. So it’s the top left corner of the player that is centered, and that’s not what we want.

HTML5 Phaser tutorial

To fix that, we will need to change the anchor point’s position. Here are some examples of how we can do that:

// Set the anchor point to the top left of the sprite (default value)
this.player.anchor.setTo(0, 0);

// Set the anchor point to the top right of the sprite
this.player.anchor.setTo(1, 0);

// Set the anchor point to the bottom left of the sprite
this.player.anchor.setTo(0, 1);

// Set the anchor point to the bottom right of the sprite
this.player.anchor.setTo(1, 1);

To center the player, we need to set the anchor point to the middle of the sprite, in the create function:

this.player.anchor.setTo(0.5, 0.5);

Add Gravity to the Player

Let’s add some gravity to the player, to make it fall. To do so, we need to add this in the create function:

// Tell Phaser that the player will use the Arcade physics engine
game.physics.arcade.enable(this.player); 

// Add vertical gravity to the player
this.player.body.gravity.y = 500;

Adding Arcade physics to the player is really important, it will allow us to use its body property to:

  • Add gravity to the sprite to make it fall (see above)
  • Add velocity to the sprite to be able to move it (see below)
  • Add collisions (see in the next part)

Control the Player

There are a couple of things that need to be done if we want to move the player around with the arrow keys.

First, we have to tell Phaser which keys we want to use in our game. For the arrow keys, we simply add this in the create function:

this.cursor = game.input.keyboard.createCursorKeys();

And thanks to this.cursor, we can now add a new function (just after the update) that will handle all the player’s movements:

movePlayer: function() {
    // If the left arrow key is pressed
    if (this.cursor.left.isDown) {
        // Move the player to the left
        this.player.body.velocity.x = -200;
   }

   // If the right arrow key is pressed
   else if (this.cursor.right.isDown) {
       // Move the player to the right
       this.player.body.velocity.x = 200;
   }

   // If neither the right or left arrow key is pressed
   else {
       // Stop the player
       this.player.body.velocity.x = 0;
   }

   // If the up arrow key is pressed and the player is touching the ground
   if (this.cursor.up.isDown && this.player.body.touching.down) {
       // Move the player upward (jump)
       this.player.body.velocity.y = -320;
   }      
},

In Phaser, the velocity is expressed in pixels per second.

And finally, we have to call movePlayer inside the update function:

this.movePlayer();

This way, we check 60 times per second if an arrow key is pressed, and move the player accordingly.

Conclusion

As usual, you should check that everything is working as expected. If so, you will be able to control the player while falling, and see him disappear from the screen.

Create the World

Having a player falling is nice, but it would be better if there was a world in which he could move around. That’s what we are going to fix in this part by doing this:

HTML5 Phaser tutorial

Load the Walls

With 2 sprites (an horizontal and a vertical wall) added at different locations, we will be able to create the whole new world.

HTML5 Phaser tutorial

As we explained previously, we need to start by loading our assets in the preload function:

game.load.image('wallV', 'assets/wallVertical.png');
game.load.image('wallH', 'assets/wallHorizontal.png');

You can see that the name of the image doesn’t have to be the same as its filename.

Add the Walls – Idea

Let’s create the left and right walls of the game:

// Create the left wall
var leftWall = game.add.sprite(0, 0, 'wallV'); 

// Add Arcade physics to the wall
game.physics.arcade.enable(leftWall); 

// Set a property to make sure the wall won't move 
// We don't want to see the wall fall when the player touches it
leftWall.body.immovable = true;

// Do the same for the right wall
var rightWall = game.add.sprite(480, 0, 'wallV'); 
game.physics.arcade.enable(rightWall); 
rightWall.body.immovable = true;

That’s 6 lines of code for just 2 walls, so if we do this for the 10 walls it will quickly become messy. To avoid that we can use a Phaser feature called groups, which let us group objects together that can easily share some properties. Here’s how it works for our 2 walls:

// Create a new group
this.walls = game.add.group();

// Add Arcade physics to the whole group
this.walls.enableBody = true;

// Create 2 walls in the group
game.add.sprite(0, 0, 'wallV', 0, this.walls); // Left wall
game.add.sprite(480, 0, 'wallV', 0, this.walls); // Right wall

// Set all the walls to be immovable
this.walls.setAll('body.immovable', true);

You may notice that the game.add.sprite has 2 new optional parameters. It’s the last one that’s interesting to us: the name of the group to add the sprite in.

Add the Walls – Code

Adding walls is not very interesting, all we have to do is to create them at the correct positions. Here’s the full code that does just that, in a new function:

createWorld: function() {
    // Create our wall group with Arcade physics
    this.walls = game.add.group();
    this.walls.enableBody = true;

    // Create the 10 walls 
    game.add.sprite(0, 0, 'wallV', 0, this.walls); // Left
    game.add.sprite(480, 0, 'wallV', 0, this.walls); // Right

    game.add.sprite(0, 0, 'wallH', 0, this.walls); // Top left
    game.add.sprite(300, 0, 'wallH', 0, this.walls); // Top right
    game.add.sprite(0, 320, 'wallH', 0, this.walls); // Bottom left
    game.add.sprite(300, 320, 'wallH', 0, this.walls); // Bottom right

    game.add.sprite(-100, 160, 'wallH', 0, this.walls); // Middle left
    game.add.sprite(400, 160, 'wallH', 0, this.walls); // Middle right

    var middleTop = game.add.sprite(100, 80, 'wallH', 0, this.walls);
    middleTop.scale.setTo(1.5, 1);
    var middleBottom = game.add.sprite(100, 240, 'wallH', 0, this.walls);
    middleBottom.scale.setTo(1.5, 1);

    // Set all the walls to be immovable
    this.walls.setAll('body.immovable', true);
},

Note that for the last 2 walls we had to scale up their width with sprite.scale.setTo(1.5, 1). The first parameter is the x scale (1.5 = 150%), the second is the y scale (1 = 100% = no change).

And we should not forget to call createWorld in the create function:

this.createWorld();

Collisions

If you test the game, you will probably see that there is a problem: the player is going through the walls. We can solve that by adding a single line of code at the beginning of the the update function:

// Tell Phaser that the player and the walls should collide
game.physics.arcade.collide(this.player, this.walls);

This works because we previously enabled Arcade physics for both the player and the walls. However, be careful to always add the collisions at the beginning of the update function, otherwise it might cause some bugs.

HTML5 Phaser tutorial

Conclusion

If you test the game, you should be able to jump on the platforms and run around. This is starting to look like a real game, and that’s just the beginning.

Discover Phaser

Want to learn how to: add enemies, coins, menus, sounds, animations, make the game mobile friendly, and much more? Then you should check out the ebook Discover Phaser.


Viewing all articles
Browse latest Browse all 1620

Trending Articles