What is a Phaser?

Phaser is an HTML5 gaming framework designed to make cross-browser HTML5 games fast. The framework takes advantage of modern browsers (both desktop and mobile), so the only requirement for a browser is to support the Canvas tag.

The first Phaser 3 game example tutorial

We’ll learn how to use Phaser with a mini-game. In this little game, a player runs and jumps around the platform, collecting stars and dodging bombs. In addition to familiarizing yourself with the Phaser API, I will also explain some of the core features of the Phaser framework.

The basic requirements

  1. Will use javascript
  2. You need a set up Web service (such as Nginx, Apache, IIS, Tomcat, and so on)
  3. Download the zip file that contains the code and resources for each step of the tutorial.

Again, you’ve read the Getting Started Guide, which guides you through how to download Phaser, set up your local development environment, and take a look at the Phaser project structure and its core apis.

If you’ve read the Getting Started Guide, you should have everything set up and ready to write code. Please download the resources required for this tutorial and unzip it to your Web server root.

The code structure

Select and open the part1.html page in the editor. Here’s a little HTML boilerplate code that introduces Phaser; The following code structure is as follows:

var config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    scene: {
        preload: preload,
        create: create,
        update: update
    }
};

var game = new Phaser.Game(config);

function preload ()
{
}

function create ()
{
}

function update ()
{
}
Copy the code

This Config object means how you configure the Phaser game. There are a number of options you can put into this object, and you’ll come across them as your Phaser knowledge increases. However, in this tutorial, we are only going to set the renderer, size, and default Scene.

An instance of the Phaser.Game object (instance) is assigned to a local variable called Game, to which the above configuration object is passed. This will begin the Phaser process.

In Phaser 2, objectsgameServes as an entry point to almost any internal system and is often accessed through global variables. This is no longer the case in Phaser 3, where storing game instances in global variables is no longer useful.

The property type can be phaser.canvas, or phaser.webgl, or phaser.auto. This is the render context you will use for your game. The recommended value is phaser.auto, which will automatically try to use WebGL and will fall back to Canvas if the browser or device does not support it. The Canvas element generated by Phaser will be added directly to the node in the document where the script is called, though you can also specify a parent container in the game configuration if you want.

The width and height properties set the dimensions of the canvas element Phaser is about to generate, in this case 800 x 600 pixels. This is the resolution the game will display, and your world can be any size.

More details on configuring the scene property of an object will be covered later in this tutorial.

Load resources

Let’s load the resources we need for the game. To do this, you call the Phaser’s Loader inside a function called preload in the scene. Phaser starts up and automatically finds this function and loads all the resources defined inside.

The preload function is currently empty. Change it to:

function preload ()
{
    this.load.image('sky', 'assets/sky.png');
    this.load.image('ground', 'assets/platform.png');
    this.load.image('star', 'assets/star.png');
    this.load.image('bomb', 'assets/bomb.png');
    this.load.spritesheet('dude', 
        'assets/dude.png',
        { frameWidth: 32, frameHeight: 48 }
    );
}
Copy the code

This will load five resources: four images and a Sprite sheet. It may seem obvious to some, but I also want to talk about the first parameter, which is called the resource’s key (‘sky’, ‘bomb’). This string is a link to the loaded resource that you will use when generating the gameobject in your code. Feel free to use any valid JavaScript string as a key.

According to the image

To display an image that has been loaded, we put the following code into the create function:

this.add.image(400, 300, 'sky');

You can see this line in part3.html. If you loaded it in your browser, you should now see a game screen with a blue sky as the background:

400 and 300 are the x and y values of the image coordinates. Why 400 and 300? This is because, in Phaser 3, all game objects are positioned based on their center point by default. The size of the background image is 800 x 600 pixels, so if we display it with its center at 0 x 0, you will only see it in the lower right corner. If we display it at 400 x 300, you can see the whole thing.

Tip: you can change this by using setOrigin. For example, code this.add.image(0, 0, ‘sky’).setorigin (0, 0) resets the drawing anchor point of the image to the upper-left corner. In Phaser 2, anchor points are obtained via the property anchor, but in Phaser 3 via the properties originX and originY.

The game objects are displayed in the order in which you generated them. So, if you want to put a star Sprite in the background, make sure you add the star image after the sky image:

function create ()
{
    this.add.image(400, 300, 'sky');
    this.add.image(400, 300, 'star');
}
Copy the code

If you put the star image first, it will be covered by the sky image.

Building a game world

At the bottom, code this.add.image generates a new image-like game object and adds it to the display list of the current scene. All of your game objects live in this list. You can place the image anywhere and Phaser won’t mind. Of course, if the image is outside the 0x0 to 800×600 area, you can’t see it visually because it’s “out of frame,” but it’s still there.

The Scene itself has no definite size and is infinite in all directions. The Camera system controls your view of the scene, and you can move, push and pull the active Camera at will. You can also generate additional lenses for other views of the scene. This topic is beyond this particular tutorial, and it’s safe to say that Phaser 3’s lens system vastly outperforms Phaser 2’s. What was completely impossible before is now possible.

Now let’s build the scene, add a background image and some platforms. Here is the updated create function:

var platforms;

function create ()
{
    this.add.image(400, 300, 'sky');

    platforms = this.physics.add.staticGroup();

    platforms.create(400, 568, 'ground').setScale(2).refreshBody();

    platforms.create(600, 400, 'ground');
    platforms.create(50, 250, 'ground');
    platforms.create(750, 220, 'ground');
}
Copy the code

With a quick glance at the code, you can see a call to this.physics. This means we’re using the Arcade Physics system, but before we can do that we need to add it to the game configuration to tell Phaser we need it for our game. So let’s update it and introduce support for physical systems. Here’s the revised configuration:

var config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    physics: {
        default: 'arcade',
        arcade: {
            gravity: { y: 300 },
            debug: false
        }
    },
    scene: {
        preload: preload,
        create: create,
        update: update
    }
};
Copy the code

What’s new is the physics property. Once the code is in place, if you run it (which you can find in the tutorial’s zip file part4.html), you’ll see a more game-like scene:

We have a background and some platforms, but how do these platforms work?

platform

We just added a bunch of code to the create function, which should be explained in more detail. First, this section:

platforms = this.physics.add.staticGroup();
Copy the code

This sentence generates a static physical Group, and assigns this Group to the local variable FFFFFF. In Arcade physics, there are two types of objects (bodies) : dynamic and static. A dynamic object can move around with a lot of external forces, like velocity and acceleration. It can bounce and collide with other objects depending on their mass and other factors.

In stark contrast, static objects only have position and size. Gravity doesn’t affect it, you can’t set its speed, it doesn’t move at all when something hits it. True to its name, it’s completely static. So it’s perfect as a floor and platform, and we’re going to have the player running around on it.

So what is a group? As the name suggests, it is a means of organizing approximate objects together, controlling them as a whole as if they were a unified entity. You can also check for collisions between groups and other game objects. Groups can generate their own game objects through handy helper functions such as create. The physics group will automatically generate children that have the physical system enabled, saving you the need to run errands.

With the platform group ready, we can now use it to generate platforms:

platforms.create(400, 568, 'ground').setScale(2).refreshBody();

platforms.create(600, 400, 'ground');
platforms.create(50, 250, 'ground');
platforms.create(750, 220, 'ground');
Copy the code

This generates the scene, as you saw earlier.

During preloading, we enter the image ‘ground’. It is a simple green rectangle measuring 400 x 32 pixels that will be used for our base platform:

For the first line of the above code, add a new ground image to the position 400 x 568 (remember, image positioning is based on the center point) — the problem is that we need this platform to cover the width of the game. Otherwise the player will fall out of bounds. To do this, we use the function setScale(2) to scale it by x2 (twice). Now it’s 800 x 64, which fits our bill. RefreshBody () is called because we are scaling a static object, so we must tell the physics world about the changes.

The ground is scaled and in position, and now it’s time for another platform:

platforms.create(600, 400, 'ground');
platforms.create(50, 250, 'ground');
platforms.create(750, 220, 'ground');
Copy the code

This step is exactly the same as before, except that there is no need to zoom, because they are already the right size.

Three platforms have been placed around the screen, at the right distance for the player to jump on.

So let’s add players.

The player

We’ve got lovely, inviting platforms, but no one’s running on them yet. Let’s change that.

Make a new variable player and add the following code to the create function. You can see these in part5.html:

player = this.physics.add.sprite(100, 450, 'dude'); Player. SetBounce (0.2); player.setCollideWorldBounds(true); this.anims.create({ key: 'left', frames: this.anims.generateFrameNumbers('dude', { start: 0, end: 3 }), frameRate: 10, repeat: -1 }); this.anims.create({ key: 'turn', frames: [ { key: 'dude', frame: 4 } ], frameRate: 20 }); this.anims.create({ key: 'right', frames: this.anims.generateFrameNumbers('dude', { start: 5, end: 8 }), frameRate: 10, repeat: -1 });Copy the code

There are two different things to do: generate a Sprite, and generate a few animations that the Sprite can use.

Physical elves

The first part of the code generates sprites:

player = this.physics.add.sprite(100, 450, 'dude'); Player. SetBounce (0.2); player.setCollideWorldBounds(true);Copy the code

This generates a new Sprite, called Player, at 100 x 450 pixels, at the bottom of the game. The Sprite is generated by the Physics Game Object Factory (this.physics.add) function, which means it has a dynamic Object by default.

Sprites are generated and given a bounce value of 0.2. That means it always bounces a little bit when it hits the ground. The Sprite then sets up a collision with bound. Boundaries are outside the game size by default. We (through player. SetCollideWorldBounds (true)) the game (world boundary) is set to 800 x 600, players will have to run out of the area. This will stop the player from going beyond the edge of the screen, or out of the top edge.

animation

If you review the preload function, you’ll see that ‘dude’ is loaded as a Sprite sheet, not an image. This is because it contains frames for animation. The complete Sprite form looks like this:

There are 9 frames, 4 running left, 1 facing the camera, and 4 running right. Note: Phaser supports flipping sprites to save animation frames, but since this is a tutorial, we’ll keep things old school.

We define two animations called ‘left’ and ‘right’. This is the ‘left’ animation:

this.anims.create({
    key: 'left',
    frames: this.anims.generateFrameNumbers('dude', { start: 0, end: 3 }),
    frameRate: 10,
    repeat: -1
});
Copy the code

The ‘left’ animation uses 0, 1, 2, 3 frames and runs at 10 frames per second. ‘repeat -1’ tells the animation to loop.

This is our standard run cycle. The animation in the opposite direction repeats this, using the key ‘right’. The last animation key is ‘turn’.

Additional information: In Phaser 3, the Animation Manager is the global system. The generated animations are global variables that all gameobjects can use. They share basic animation data and manage their own timeline. This allows us to define one animation at a time that can be applied to as many game objects as we want. This is different from Phaser 2, where the animation only belongs to the specific gameobject from which the animation was generated.

Adding a Physical System

Phaser supports a variety of physical systems, each of which operates as plug-ins that can be used by any Phaser scenario. At the time of writing, Arcade, Impact, and Matter.js are available. For this tutorial, we’ll use Arcade physics for our game, which is simple, lightweight, and perfectly mobile browser friendly.

When a physics Sprite is generated, it is given the body property, which points to the body of its Arcade physics system. It indicates that the Sprite is an object in the Arcade physics engine. Object Objects have a lot of properties and methods that we can play around with.

For example, to simulate the effect of gravity on a Sprite, it could be written as follows:

player.body.setGravityY(300)

This is an arbitrary value, but logically, the higher the value, the heavier your object will feel and the faster it will fall. If you add this to your code, or run part5.html, you’ll see that the player keeps falling, completely ignoring the ground we generated earlier:

The reason is that we haven’t tested the collision between the ground and the player yet.

We’ve told Phaser that our ground and platform will be static objects. But instead of doing that, we generated dynamic. This way, when the player collides with them, the player stops for a second and then collapses. This is because, unless you say otherwise, a ground Sprite is a moving object, and when the player touches it, the force of the collision acts on the ground, so the two objects exchange their speed and the ground starts falling.

To allow the player to collide with the platform, we can generate a collision object. This object monitors two objects (which can be groups), detecting collisions and overlapping events between them. If an event occurs, then it can call our callback function at will. But just for collisions with platforms, we don’t have to do that:

this.physics.add.collider(player, platforms);
Copy the code

A Collider is a place where magic can be done. It takes two objects, detects collisions between them, and separates them. In this case, we give it the player Sprite and platform group. It is clever enough to perform collisions for all group members, so this single call can handle collisions with combinations and all platforms. The result is a solid platform that no longer collapses:


Keyboard control

Collisions are great, but we really want the player to move. You might be tempted to go to the documentation and look up how to add event listeners, but that’s not necessary here. Phaser has a built-in keyboard manager, and one of the benefits of using it is this handy little function:

cursors = this.input.keyboard.createCursorKeys();

Put the four properties up, Down, left, and right (all instances of the Key object) into the cursor. Then we need to do some polling in the update loop like this:

if (cursors.left.isDown)
{
    player.setVelocityX(-160);

    player.anims.play('left', true);
}
else if (cursors.right.isDown)
{
    player.setVelocityX(160);

    player.anims.play('right', true);
}
else
{
    player.setVelocityX(0);

    player.anims.play('turn');
}

if (cursors.up.isDown && player.body.touching.down)
{
    player.setVelocityY(-330);
}
Copy the code

We’ve added a lot of code, but it’s still fairly readable.

The first thing it does is check to see if the left direction button is being pressed. If so, we apply a negative horizontal speed and start the running animation ‘left’. If the directional right button is being pressed, we literally do the reverse. By clearing the speed value and setting it so, frame by frame, it creates a stop-start movement.

The player Sprite moves only when the key is pressed and stops immediately when it is lifted. Phaser also allows you to use momentum and acceleration to generate more complex actions, but here we have the desired effect for our game. At the end of the keyboard detection, if no key is pressed, the animation is set to ‘turn’ and the horizontal speed is 0.

Hurry up

The jump function is added at the end of the code. The up key is the jump key, and we check to see if it’s pressed. But we also check to see if the player is making contact with the ground or jumping in mid-air.

If all these conditions are met, we apply a vertical velocity of 330 pixels per second. The player will automatically fall back to the ground because of gravity. With the controls in place, we now have a game world to explore. Please load part7.html and play with it. Try adjusting each value, such as the jump value of 330, down, up and see what happens.

Collect the stars

It’s time to set a goal for our little game. Let’s sprinkle a few stars into the scene and let the player collect them. To do this, we’ll create a new group called ‘stars’ and fill it out. In the generated function, we add the following code (which can be seen in part8.html) :

stars = this.physics.add.group({ key: 'star', repeat: 11, setXY: { x: 12, y: 0, stepX: 70 } }); Stars.children. Iterate (function (child) {child.setbouncey (phaser.math.floatBetween (0.4, 0.8)); });Copy the code

This process is similar to how we generate platform groups. Because the stars need to move and bounce, we generate dynamic physics groups, not static ones.

Groups can receive configuration objects for easy setting. In this case, the group configuration object has three parts: First, it sets the texture key to the star image. This means that all children generated by configuration objects will be textured with stars by default. It then sets the repeat value to 11. Since it automatically generates a subitem, repeating it 11 times means we’ll get 12 in total, which is exactly what our game needs.

The last part is setXY — this sets the position of the group’s 12 children. Each subterm will be placed as follows: x: 12, y: 0, then x steps 70. That means the first subterm is going to be 12 x 0; The second one leaves 70 pixels and is located at 82 x 0; The third one is 152 x 0, and so on. The ‘step’ value is a handy way to arrange groups when they generate children. The value of 70 was chosen because it meant that all 12 subitems would fit perfectly across the screen.

The next code iterates through all the children in the group, giving them a random value of bounce. Y between 0.4 and 0.8, with a bounce range of 0 (no bounce) to 1 (full bounce). Because stars are produced at y equals zero, gravity will pull them down until they collide with a platform or the ground. Rebound values mean they will bounce up randomly until they finally settle down.

If we run the code like this now, the star will fall across the bottom of the game and disappear. To prevent this problem, we detect their collision with the platform. We can do this with another collider object:

this.physics.add.collider(stars, platforms);

Similarly, we will check if the player overlaps with the stars:

this.physics.add.overlap(player, stars, collectStar, null, this);

This tells Phaser to check the player’s overlap with any of the stars in the group. If detected, they are passed to the ‘collectStar’ function:

function collectStar (player, star)
{
    star.disableBody(true, true);
}
Copy the code

Simply put, the star carries a closed object, and its parent gameobject is set to inactive and invisible, removing it from the display. Now running the game, we get a player that darts, jumps, bounces off the platform, and collects falling stars from overhead. Not bad, after all, just a few lines of mostly fairly understandable code 🙂


The scoring

Finally, we decided to add two improvements to the game: an enemy to dodge, which would kill the player; Score points when you collect stars. The first is scoring.

To do this, we’ll use the gameobject Text. Here we generate two new variables, one that holds the actual score and the text object itself:

var score = 0;
var scoreText;
Copy the code

ScoreText is built in the create function:

scoreText = this.add.text(16, 16, 'score: 0', { fontSize: '32px', fill: '#000' });

16 x 16 is the coordinate position to display the text. ‘Score: 0’ is the default string to display, followed by an object containing the size and padding. Because no font is specified, you will actually use the Phaser default, Courier.

Next we’ll tweak the collectStar function so that when the player picks up a star the score goes up and the text is updated to reflect the new state:

function collectStar (player, star)
{
    star.disableBody(true, true);

    score += 10;
    scoreText.setText('Score: ' + score);
}
Copy the code

This adds 10 points to each star, and the scoreText will update to show the new total score. If you run part9.html, you can see the stars fall and the score increases when you collect them.

We’ll add some bad guys to the last section.

Egg up and down,

Now it’s time to add some bad guys to wrap up our game. This adds a great element of challenge to the game that has been lacking before.

The idea is this: after you collect all the stars for the first time, you will release a bouncing ball. This bomb just randomly bounces around the platform, and if you collect it, you die. All the stars are regenerated so you can collect them again, and if you finish, another bomb is released. This gives the player a challenge: don’t die and get as high a score as possible.

The first thing we need is a set for the bomb, and a couple of colliders:

bombs = this.physics.add.group();

this.physics.add.collider(bombs, platforms);

this.physics.add.collider(player, bombs, hitBomb, null, this);
Copy the code

Bombs will of course jump off the platform, and if the player touches them, we’ll call the “hitBomb” function. All this function does is stop the game and make the player turn red:

function hitBomb (player, bomb)
{
    this.physics.pause();

    player.setTint(0xff0000);

    player.anims.play('turn');

    gameOver = true;
}
Copy the code

So far, so good, but we’re gonna drop a bomb. To do this, let’s change the collectStar function:

function collectStar (player, star) { star.disableBody(true, true); score += 10; scoreText.setText('Score: ' + score); if (stars.countActive(true) === 0) { stars.children.iterate(function (child) { child.enableBody(true, child.x, 0, true, true); }); var x = (player.x < 400) ? Phaser.Math.Between(400, 800) : Phaser.Math.Between(0, 400); var bomb = bombs.create(x, 16, 'bomb'); bomb.setBounce(1); bomb.setCollideWorldBounds(true); bomb.setVelocity(Phaser.Math.Between(-200, 200), 20); }}Copy the code

Let’s use a group method, countActive, to see how many stars are still alive. If not, then the player has collected them, and we use the iterative function to reactivate all the stars, resetting their y position to 0. This will cause all the stars to fall from the top of the screen again.

The next part of the code generates a bomb. First, we give it a random X-coordinate, always on the opposite side of the player’s screen, to give the player a chance. Then build the bomb, set it to collide with the world, bounce, and have random speed.

The end result is a nice little bomb Sprite that bounces around the screen. Small in size and easy to avoid at first. But as the numbers increase, it gets trickier!

Our game is ready 🙂

conclusion

Now you’ve learned how to generate a Sprite with physical properties, how to control its actions, and how to make it interact with other objects in a small game world. There are many things you can do to enhance it. Why not expand the size of the platform and allow the lens to wobble? Maybe add different types of bad guys, different points to collect, or give the player a health bar.

Or, to be nonviolent, you could make it a speed-run game that simply challenges people to collect stars as fast as possible.

With everything you’ve learned in this tutorial, and the help you get from hundreds of examples, you now have a solid foundation for future projects. But you’ll always have questions, need advice, or want to share something you’ve been working on, so feel free to ask for help in the Phaser forum.

Facebook Real-time Games

Phaser 3 fully supports generating Facebook real-time games. Now that you’ve learned how to make Phaser games, why not take a look at how to easily convert to real-time games? It’s in our special guide to getting started.