Does your game have a main menu with options that can be selected using the keyboard arrow keys or a controller's D-pad?
Maybe it is something inspired by Final Fantasy, Harvest Moon, or Super Mario Bros?
Great choice! They are tried and true UI mechanics but perhaps you are unsure of how to move a selection cursor to the correct button or know which button is then selected? 🤔
If that's the case then this article is what you're looking for! We'll show you how to create a menu like this 👇 for any number of items.
This example will consist of one Scene that loads a button image and a cursor hand image. Both images are from Kenney's UI Pack: Space Expansion.
But if you would like to learn more about making games in Phaser 3 and TypeScript then we have a great, free book to help you get started!
Learn to make an Infinite Runner in Phaser 3 with TypeScript!
Drop your email into the box below to get this free 90+ page book and join our newsletter.
Here's what our barebones Scene looks like:
We create a
cursors class property to store an instance of
CursorKeys for simple access to the
space keys. They will be used to move our selection up and down as well as confirm the selection.
create() method is where we will create the menu buttons. The 3 other methods will handle selecting the appropriate menu items.
Notice that we use
selectNextButton() in the
update() method when
down is pressed. This is where our logic for moving to the next button will go.
confirmSelection() method is called when the
space key is pressed for taking an action associated with the selected button.
Creating Menu Buttons
We'll create 3 buttons in a vertical layout for Play, Settings, and Credits.
Each button will consist of an
Image with a
Text object layered on top of it.
Now that we have 3 buttons, we can keep track of where a selection cursor should go by storing the buttons in an Array and keeping track of which index is currently selected.
Let's do that by creating two new class property called
create() we can add the 3 buttons to the
buttons Array like this:
Lastly, we can add the hand cursor to the Scene and store a reference to it in a class property called
We use a class property to store a reference to the hand cursor so that we can adjust its
y position in
Selecting a Button
Now that we've created the menu we can implement the
selectButton(index) method to move the
buttonSelector and tint the selected button.
This method will retrieve the
Image from the
this.buttons Array using the passed in
index and set it as the newly selected button.
It unselects the currently selected button by setting the tint back to white.
Then it gives the newly selected button a green tint and moves the
buttonSelector to be over the right edge of the button.
Lastly, it sets
this.selectedButtonIndex to the passed in
Add a call to
this.selectButton(0) in the
create() method to start the menu with the first option selected:
Selecting the Next Button
selectButton(index) method implemented, selecting the next button up or down is as simple as passing in an
index value that is
+1 from what
selectNextButton(change) should look like:
The bulk of the code in this method just wraps the
index value to
0 if it exceeds the length of the array or to
this.buttons.length - 1 if it goes under zero. This will keep
index within the bounds of the Array.
selectNextButton() is called by the
update() method when the
down keys are pressed.
-1 will result in selecting the button above the current one and
1 will result in selecting the button below.
This menu is almost completely functional! The last thing is to confirm the selection.
Confirming a Selection
Buttons are usually activated by a mouse click or a touch. How would we do it using the
space key? 🤔
We can use the
EventEmitter instance that exists on every
GameObject. You may have used something like
.on('click', this.handler) with a
We can do something similar to that by emitting a different event name in
Then to use the
'selected' event we just need to listen to it after we create each button like this:
Now, when you press
space the selected button will get an event named
'selected' and the handler will get called.
You can replace the example
console.log() with more appropriate logic like going to a different Scene.
One final thing to remember is that each
.on() should have a matching
.off() to ensure that events are cleaned up. Something like this:
This seemingly simple menu selection mechanic took quite a bit of explaining!
You can extend this with as many buttons as you need and use it anywhere you have a selection menu. Perhaps in a dialogue box that asks for player input? 🧐
For cases where the location of the selection cursor on each button can be different, store an offset with each button reference instead of just the button in the
Be sure to sign up for our newsletter so you don't miss any future Phaser 3 game development tips and techniques!
Drop your email into the box below.
Don't miss any Phaser 3 game development content
Subscribers get exclusive tips & techniques not found on the blog!
Join our newsletter. It's free. We don't spam. Spamming is for jerks.