Scoreboard
In this step we are going to add a scoreboard that displays how many coins the main character has collected:
In order to do that, we need to be able to write text in the screen. In games, this can be done in different ways:
- By using a regular TTF font, like Times New Roman (for HTML5 games this could be a Web Font)
- By using a bitmap font, which is actually a spritesheet, and render the characters one by one like they were images.
For the scoreboard we will use a bitmap font, which are called in Phaser retro fonts. The font will consist only of digits, a blank space and an x
character. Here's the spritesheet:
It's important to know that in order to render a text with a bitmap font, we need both an instance of Phaser.RetroFont
and an instance of Phaser.Image
. Why? The retro font holds the image data in memory (i.e. the pixel values of a rendered text), but then we need a Phaser entity that can make use of that image data, such as Phaser.Image
(or even Phaser.Sprite
)!
Tasks
Keep track of how many coins have been collected
We only need a property in
PlayState
to do this. We are initialising it to zero ininit
, and then increasing this counter when a coin is picked up:PlayState.init = function () { // ... this.coinPickupCount = 0; };
PlayState._onHeroVsCoin = function (hero, coin) { // ... this.coinPickupCount++; };
Draw a coin icon on top of everything
Load the image asset in
preload
:PlayState.preload = function () { // ... this.game.load.image('icon:coin', 'images/coin_icon.png'); // ... };
We will separate the creation of UI elements into a separate method. Inside it, we will create a new group to store all the UI icons, text, etc.
PlayState._createHud = function () { let coinIcon = this.game.make.image(0, 0, 'icon:coin'); this.hud = this.game.add.group(); this.hud.add(coinIcon); this.hud.position.set(10, 10); };
Note how all entities inside
this.hud
will get rendered relatively to it. This means that, since the hud is in position(10, 10)
, if we draw an image at –for instance–(5, 5)
, it will get rendered at position(15, 15)
of the screen.Since the HUD must be rendered on top of everything else, it should be created after spawning all the elements in the level:
PlayState.create = function () { // ... this._createHud(); }
Check that the coin icon is rendered at the top left of the screen:
Write the text
Finally we get to the most interesting part! As usual, we need to load the asset that will make up the font. Note that, even though conceptually it is a spritesheet, in Phaser it needs to be loaded it with
load.image
:PlayState.preload = function () { // ... this.game.load.image('font:numbers', 'images/numbers.png'); // ... };
Now we need to instantiate
Phaser.RetroFont
, that will be able to compute how a text looks like with the bitmap font spritesheet.PlayState._createHud = function () { const NUMBERS_STR = '0123456789X '; this.coinFont = this.game.add.retroFont('font:numbers', 20, 26, NUMBERS_STR, 6); // ... };
Since Phaser has no idea of the contents of the spritesheet, we need to tell it when creating the retro font: the width and height of each character and which characters are being included (the orden is important!)
With the retro font created, we need to make use of it from a game entity. We will use a
Phaser.Image
for this:PlayState._createHud = function () { // let coinIcon = ... let coinScoreImg = this.game.make.image(coinIcon.x + coinIcon.width, coinIcon.height / 2, this.coinFont); coinScoreImg.anchor.set(0, 0.5); // ... this.hud.add(coinScoreImg); };
Last, we just need to tell the retro font which text string to render.
PlayState.update = function () { // ... this.coinFont.text = `x${this.coinPickupCount}`; };
Try it in the browser and see how the text changes with every coin collected!
Download
Are you stuck? Take a look at the source code for this step.