If you've gone through the basic first game in modern JavaScript or the infinite jumper book then you've got the basics down so let's try making something a little bit more complicated!
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 3, we added logic to determine when a box can be opened to reveal the item inside.
Now in part 4, we will show you how to check for a match and handle the two possible outcomes: match or no match.
We also have a video version on YouTube if you prefer to watch or want to see how it is coded in real-time.
Fixing Depth Sort
You've likely noticed that the item revealed by a box depth sorts behind the box and the player depending on where he is.
This is because we are calling setDepth()
on all children in update()
. We could avoid this by adding the children that we want to sort to a list and only calling setDepth()
on those GameObjects
.
But, we will show you another way using setData()
to flag certain GameObjects
.
Add this to the openBox()
method:
|
|
We give the item
a flag with the key 'sorted'
and then set its depth to a relatively high number of 2000
so that it will be on top of everything else.
The 'sorted'
flag will then be used in the update()
method like this:
|
|
Now, revealed items will always be above everything else in the game.
Disallow Open Boxes from Opening Again
Since we fixed one bug, let's fix another! You'll notice that you can open a box that has already been opened.
That doesn't seem right. We can fix that quite easily because we've already added an 'opened'
flag to each box that is opened.
Add this to handlePlayerBoxCollide(player, box)
in the Game
Scene:
|
|
We simply check if a box is opened and then early exit if it is. Easy peasy.
Checking for a Match
A match can happen after two newly opened boxes have revealed their items.
We can check for this after the tween that reveals the item. But first, we need to store the last two opened boxes and revealed items in an Array to only check the newly opened boxes and not all open boxes.
Add a selectedBoxes
class property like this:
|
|
Then we will push the opened box and revealed item to this list in openBox()
before we create the tween:
|
|
Recall that we defined the selectedBoxes
Array as containing an object with a box
and item
property. That's why we are pushing an object with a box
and item
property on line 6.
We are using a modern JavaScript shorthand to create the object by automatically using the variable name as the key. You can also write it like this:
|
|
This modern syntax removes the need to type the same thing twice.
Next, we want to check if there are 2 open items after an item has been revealed. We can do that by using the onComplete
callback provided by a tween.
|
|
If we do not have at least 2 items opened then we early exit and wait until a second box is opened.
Once 2 boxes have been opened, we will call the checkForMatch()
method that looks like this:
|
|
We start by calling pop()
twice to get the selected boxes in the reverse order they were added. This means the first one popped is the second box opened.
You could compare against index 0
and 1
but we feel using a human-readable variable name is easier to think about. 🤗
Then we determine if there is no match by comparing the texture
property of the revealed items. This will compare the texture key that each item is using such as: 'duck'
, 'parrot'
, etc.
When there is no match, we tween both items away by doing the reverse of what we did to reveal them. We also call killAndHide()
on each item to properly set them to inactive so that they can be reused later. Both boxes also set their 'opened'
flags to false
so the player can try them again.
If there is a match, we wait 1 second and then set each box
to use the frame at index 8
which is a blue box.
Try it out and you'll see matched items staying on-screen while unmatched items go back into their boxes. 👏
Reset Reused Items
Let's wrap up by making sure that reused items from the itemsGroup
are set to active and visible when they are to be revealed.
Because we used killAndHide()
to properly set each unmatched item to be inactive, we also have to make sure to reactivate them when we call this.itemsGroup.get()
because we can be getting a reused Sprite
.
All we need to do is add these two lines to the openBox()
method:
|
|
Next Steps
We fixed a couple of bugs and implemented logic to handle matches. But you'll notice that we haven't handled the bear or when all matches have been made.
That's what we'll do in part 5! The bear will act as Bowser and stun the player for 1 second.
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.