monetization

Phaser 3 HTML5 Title Screen Tutorial

Most HTML5 games will have a title screen at one point or another, and in Phaser 3 it's very easy to add and get started. This tutorial is going to work through the basics of adding your own title screen to your game, allowing you to switch between different scenes and start your original game. We'll be using Phaser 3 as our HTML5 game engine library, so if you're new to Phaser 3, we recommend checking out our Phaser 3 beginner tutorial in which we create a very basic game to learn the fundamentals of the framework.

Phaser 3 Title Screen Tutorial

In this tutorial we'll explain how to do the following in Phaser 3:

  • Creating Multiple Scenes
  • Separating our scenes into multiple files and extending the scene class
  • Buttons
  • Switching Scenes

A title screen is basically just another scene in our HTML5 game. A title screen usually is an introduction to the game, it presents the game you're about to play to the user, perhaps with some instructions and options that the player can tweak (turning off sound etc). It's a much more user friendly way of playing a game to allow the user to select when to begin the game, rather than just dumping the user directly into the game before they have a chance to see what they're about to play.

In our last tutorial we created a basic game scene that handled all our game logic. If you remember it had four main functions:

  • Init - Created our game values such as score, speed etc
  • Preload - preloads all our images into the game
  • Create - setup the scene by placing our assets in the right positions
  • Update - the game logic which runs every 60 times a second
  • End - the gameover logic

Phaser 3 allows us to create multiple scenes at a time- we could create a game within a game if we wanted. For a title screen, we don't need to use the update() function (unless you want to of course). We are going to be using just the preload() and create() functions. But first, let's take a look at how we create multiple scenes for a game.

Creating Multiple Scenes in Phaser 3

There are two ways we can create multiple scenes for our game. One method would be to put all our scenes in the same game file and just have one big collective mess of code. The other option is to separate our scenes into multiple files and extend the Phaser 3 scene object. For clarity sake, let's look at how we would add multiple scenes in the same game file. If you remember our game.js file from last time:

 

// Our game scene
var scene = new Phaser.Scene("game");

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

// Create the game with our config values
// this will also inject our canvas element into the HTML source 
// for us
var game = new Phaser.Game(config);

scene.init = function() {

};

scene.preload = function() {

};

scene.create = function() {

};

scene.update = function() {

};


scene.end = function() {

};

 

In the config object we created, we set the scene to use our game scene object. To have multiple scenes, we are going to remove this from the config and instead create our game object without any scenes added. We'll then create another scene called titleScene and add it to the game object using the game's scene manager.

titleScene will be created in the exact same way as our game scene. But we won't use the init(), update() or end() functions. All we need is preload() and create() functions. We'll also rename scene to gameScene to make it more understandable now that we are working with multiple scenes. Take a look at the code below:

 

// Our scenes
var gameScene = new Phaser.Scene("game");
var titleScene = new Phaser.Scene("title");

gameScene.init = function() {

};

gameScene.preload = function() {

};

gameScene.create = function() {

};

gameScene.update = function() {

};


gameScene.end = function() {

};

titleScene.preload = function() {

};

titleScene.create = function() {

};

// We no longer add the scene to the config
var config = {
	type: Phaser.AUTO,
	width: 800,
	height: 600,
};

// Our game Object
var game = new Phaser.Game(config);

// Add both scenes (it does not start them)
game.scene.add('titleScene', titleScene);
game.scene.add("game", gameScene);

// Start the title scene
game.scene.start('titleScene');

 

As you can see from the code above, we now have two scenes that we created from Phaser.Scene objects. We then create our functions for each scene that we are going to use: gameScene uses init, preload, create, update and end. titleScene uses: preload() and create().

Now that we have our skeleton of code done, let's add a simple background to our title scene and some text to welcome the player.

 

titleScene.preload = function() {
    this.load.image('background', 'images/background.jpg');
};

titleScene.create = function() {
    var bg = this.add.sprite(0,0,'background');
    bg.setOrigin(0,0);

    var text = this.add.text(100,100, 'Welcome To My Game!');
};

 

Reload the game and you should see that the titleScreen loads first before the game scene. Perfect! We are using the same process for adding sprites and text that we learnt in the first tutorial, so this should be nothing new. We now have two scenes in our game, but we can't really access the game scene just yet. Before we learn how to do that, let's look at how we can make our code more sustainable by separating our scenes into different files.

Extending the Scene Class in Phaser 3

Imagine you have a game that has ten or fifteen different scenes. Your game file is going to become huge, complicated and probably end up in a mess. We can clean up our code by using multiple files for our scenes by extending the Phaser 3 scene class. Let's do that for code we've just written. Create two new files: gameScene.js and titleScene.js:

titleScene.js:

 

class TitleScene extends Phaser.Scene {

	constructor() {
		super({key:'titleScene'});
	}

	preload() {
		this.load.image('background', 'images/background.jpg');
	}

	create() {
		 var bg = this.add.sprite(0,0,'background');
		  bg.setOrigin(0,0);

		  var text = this.add.text(100,100, 'Welcome to my game!');
	}

}

export default TitleScene;

 

for gameScene.js you want to copy the gameScene code that we had before but wrap it in a class like we did for TitleScene. For the sake of this tutorial, I'm not going to paste all the code but a skeleton version so you know how to do it:

gameScene.js:

 

class GameScene extends Phaser.Scene {

	constructor() {
		super({key : 'gameScene'});
	}

	init() {
		
	};

	preload() {
		
	}

	create() {
	   

	}

	update() {

	}


	end() {
		
	}

}

export default GameScene;

 

So a couple of things we need to take a look at with our two new game scenes.

Extending a class allows us to use the original class's methods. Since we are extending the Phaser.Scene class, we want to be able to use the Phaser 3 scene default functions such as init(), create() and update(). When we extend the Phaser.Scene class, we need to use the default constructor of that class first to initiliase it (like when we create a new scene object using new Phaser.Scene("titlescene");). To do that, we call our own constructor method and inside that use the super() function; super() basically calls the class we have extended from's constructor. We pass in a set of parameters to the Phaser.Scene constructor, which for now all we want to pass is the key of our scene so we can identify it. It's similar to calling: var scene = new Phaser.Scene("game");, but instead we call it inside our class as we have extended the Phaser.Scene object. Whenever you use the new object() method, we are calling that classes' constructor.

Since we extend the Phaser.Scene class, we now name our functions as methods of that class (rather than extending the objects functions within the file). So where

gameScene.init = function() {

now just becomes

init() {

.

 

We also have to add export default GameScene; to the end of our scene files so that we can then import them into our main game file.

Let's do that now. Importing the files directly into our game and replacing the old code we had in game.js:

 

import TitleScene from './titleScene.js';
import GameScene from './gameScene.js';

// Our game scene
var gameScene = new GameScene();
var titleScene = new TitleScene();


//* Game scene */
var config = {
  type: Phaser.AUTO,
  width: 800,
  height: 600,
};
var game = new Phaser.Game(config);

// load scenes
game.scene.add('titleScene', titleScene);
game.scene.add("game", gameScene);

// start title
game.scene.start('titleScene');

 

Doesn't our code look cleaner and more organised?

Importing other scenes into our game requires us to use the import [classname] from [file location] code. We can then create our scenes by initialising those scene objects (since they extend the Phaser.Scene object anyway) like so: var titleScene = new TitleScene();.

We now have all our scenes in separate files and can make our changes to our code much easier. We've also learned how to extend the Phaser.Scene class.

Buttons in Phaser 3

What good is a Title Screen if we can't use it to load our game scene up? To do that we'll be creating a button that we can click on that then switches to the game scene.

A button can be any game asset we have added to our scene. We can make text a button, an image and even the background. To make an asset a clickable button we need to use the setInteractive() method on it. Returning to our titleScene.js file, let's make our Welcome To Game text a button:

 

var text = this.add.text(100,100, 'Welcome to my game!');
text.setInteractive({ useHandCursor: true });

 

We pay an object {} to setInteractive which contains the variable useHandCursor : true. When we hoverover the text now, the cursor will display as a clickable action to signify the element is clickable.

Next we want to extend our text to call a function when clicked.

 

 var text = this.add.text(100,100, 'Welcome to my game!');
 text.setInteractive({ useHandCursor: true });
 text.on('pointerdown', () => this.clickButton());

 

We use the on() method for our clickable element and assign it the function on clickButton() whenever the event "pointerdown" is fired on it (clicking). There are many other events we can listen for, but check out this great blog post on Phaser 3 Buttons for more details.

We now just need to add our clickButton function to our titleScene.js file. In this function we are going to switch from the titleScene to the gameScene.

 

clickButton() {
    this.scene.switch('gameScene');
}

 

It's as simple as that.

We use Phaser 3's scene.switch() method to switch to the gameScene. The gameScene is already added to our game because in game.js we used game.add.scene("gameScene");. The switch method puts our titleScreen to sleep and starts up the gameScene. There are many different ways of starting a scene, so you should read the Phaser 3 documentation for scene manager to get a better idea of the different types. You can add in more buttons to your gameScene to take you back to the titleScreen by calling this.scene.switch('titleScene');.

Hopefully this tutorial gives you a good insight for creating Title Scenes and how you can move between one scene and another. The next tutorial will involve creating a Preloading screen, which loads up whilst the game adds all the assets into the game. This is a great way to show the user the game is loading if you have lots and lots of large assets to preload.

Let me know in the comments if you found this useful or need something else explaining!




Enjoyed that? Check These Posts Out

Sager NP8377 Gaming Laptop Review

Using Datatables with CodeIgniter Tutorial

Fullcalendar with PHP and CodeIgniter - Adding Events - Part 3

Datatables with CodeIgniter – Server Side Sorting – Part 3

...
monetization

Article Comments

Let us know your thoughts below by adding a quick comment!

21/08/2020

Uladzislau

Very helpfull!!! Thanks

Reply

26/11/2020

Juan

Thanks, it helped me understand how to switch between scenes. One thing that could possible improve the article or maybe something for another article is how to share data among scenes.

Reply

Leave A Comment