We suggest Memory Match. A Mario Party-inspired memory game where you control a character to pick boxes until all matches are found within a limited amount of time.
In part 2, we added a 3x3 grid of boxes with depth sorting to make sure everything is layered properly.
For part 3, we are going to start selecting boxes and revealing what is inside of them.
We also have a video version on YouTube if you prefer to watch or want to see how it is coded in real-time.
When a Box Can Be Opened
The player will be able to open a box by pressing the space key. But first, we need to know which box the player wants to open.
There's a couple of ways to do this and we will take the simplest approach by designating a box active when the player collides with it.
Update the code that creates a collider like this:
We broke this line up into multiple lines for ease of reading. You are free to keep it as one line if you prefer.
The main thing to notice is the addition of the
this.handlePlayerBoxCollide callback and the passing of
this as the last argument.
This will allow Phaser to call our
handlePlayerBoxCollide() method with the context set to
this so that we can continue to reference properties on the Scene.
Next, let's create the
This method simply sets the passed in
box–which represents the box the player collided with–and sets it as the
activeBox. Then it changes the frame to
9 so that it is displayed as a green box instead of the gray one.
activeBox is a class property. Remember to add it as a property declaration like this:
Run into a box and you'll see it turn green. ✅
Now, we need to change it back to being gray when the player is too far and can no longer open it.
When a Box is No Longer Active
We will consider an active box to no longer be active when the distance between the player and the
activeBox is greater than
Let's start by adding an
First, we early exit and do nothing if
this.activeBox is not set. This happens on lines 3 - 6.
Then we get the distance between the player and the currently active box. We'll do nothing if that distance is less than 64.
Once the distance is 64 or greater, we set the
activeBox back to using frame
10 and set
undefined to designate that no box is currently active.
Give this a try by adding a call to
updateActiveBox() in the
update() method after the player movement code.
You should now see that touching a box sets it to be active and then walking away sets it to not active.
What's in a Box?
We'll need to have something in each box before we open them or there will be nothing to show!
There are many ways to do this as well and we will use the simplest approach of creating a 2D array at the top of
Game.js that defines what is inside each box.
level variable after the module imports like this:
Each unique number in this 2D array represents a different animal that will come out of the box.
You can use strings if that is easier to understand but it is often easier to visually align a 2D array with numbers because words can vary widely in length.
For numbers to work, we just need to agree that
0 is a Bear,
1 is a Chicken,
2 is a Duck,
3 is a Parrot, and
4 is a Penguin.
Next, let's change how we create the boxes to use the
level array instead of a hard-coded row and column size.
We replaced the hard-coded
3 in the
for loops to use
Then we call
setData() on each created box and give the
'itemType' key the value from
level[row][col]. This value is the number representing which animal should be revealed by the box.
'itemType' key is just something that we decided to use. You can use any string with
setData() to store arbitrary data with a
Preload Animal Textures
We'll need to preload each texture for the 5 different animals that can be revealed by a box.
Download the Animal Pack Redux by Kenney here if you haven't already.
You'll need these images:
Pick out the variants that you like best. There's round, square, outlined, and others.
Then add them to the
Preloader Scene like this:
Opening a Box
Now that each box knows what it can reveal, we can add logic to open a box.
Start by adding this
This code is fairly straight-forward. We get the value stored in the
'itemType' key of each box. Then we use a
switch statement to create the appropriate
Sprite for the given type.
Next, we want to specify that the
box is opened and then tween the
item from a
1 so that it appears with a bit a fanfare.
We need to call this method to see it in action so let's make pressing the space key call
Add this to the
update() method right above the
Now when you make a box active and press space, an item will animate-in and become revealed. 🎉
Quick Code Clean Up
We'll wrap up with some quick code clean-up. You may have noticed that instead of creating a new
Sprite each time a box is opened we can reuse
Sprites by using a
Recall that we used a
Group for boxes to make it easier to add colliders but reusing
GameObjects was another benefit.
We can make the change by creating a new class property called
itemsGroup like this:
Next, update the
switch statement handling
itemType to look like this:
Take note that we are using
item.setTexture() instead of passing in the texture key to
this.itemsGroup.get(). We do this because items are being reused and this ensures the actual texture we want will be used and not the previously used texture.
The second item to improve is the
update() method as it looks a bit cluttered now.
Let's simplify it by moving the player movement logic into a separate method so that
update() is easier to read.
update() to look like this:
Items are being revealed but we don't have any logic to check if a match was made.
In part 4, we will check for matches and then handle what happens when there is a match and when there is no match.
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.