We are now halfway through this series, and so far we’ve covered a lot. In the previous tutorial, we added a points system to our game, we finally applied “gravity” to the blocks, and we improved our matching system. In this tutorial we are going to make some small improvements to our swapping system, add the floating points text you can see in the final version of the game, and finish our matching system once and for all.
1. Improving the Swapping Mechanics
Right now, the game has a very simple swapping mechanic implemented. While the system we use to perform these swaps is very effective, there are two issues that you could encounter while playing, and both of them should be fixed before we go any further.
These issues stem from the same idea: that the swapping system does not take into account the game field’s borders.
To the Left, to the Right
What does this mean, exactly? Well, first, if you wanted, you could move a block outside of the game field to the left or right, by making a swap like the one illustrated below:
If you go into the game and make this swap, you will see that the game doesn’t do anything to stop you, and acts as if the game field continues forever in a horizontal direction. The reason for this is that, right now, the game field does continue forever horizontally.
Since we never defined where the left and right borders of the game field are, or even that the game field has left and right borders, the game never attempts to stop the player from moving the block further to the side. This problem also comes up when you swap off the other edge of the game field as well.
To solve this issue, we’ll add some new conditions to the Block > On DragDrop drop
Event. Go to this event and add this condition to the Sub-Event which checks for left swaps:
Condition: LeftBlock>Compare X Comparison = Greater or equal X = SPAWNX
Now add this condition to the Sub-Event which checks for right swaps:
Condition: RightBlock>Compare X Comparison = Less or equal X = SPAWNX + Block.Width*8
Your left and right swapping events should now look like this:
These new conditions we added are being used by the swapping events as a check to ensure that the swap is within the horizontal borders of the game field. The first one ensures that the position the block would be swapped to is not farther to the left than the left-most Blocks, and the second one ensures that the position the block is being swapped to is not farther to the right than the right-most blocks.
With the second one, I used a formula with Block.Width
to find where the right-most blocks are to ensure that, if the size of the Blocks changed, it would not prevent this condition from working.
If you run the game you should no longer be able to make horizontal swaps that would put blocks outside the game area.
Out of Bounds
The other problem we have is that the game doesn’t stop you from swapping a block below the game field. Open the game and try making a swap like the one I have illustrated in this image:
After making this swap, you should have seen the block essentially just disappear behind the bottom piece of the game field, and the blocks that were above it should have fallen to fill in the now empty space. Again, this problem is because we never defined where the bottom edge of the field is.
In the previous tutorial we declared that the blocks should stop falling after reaching a certain height, but we never said whether it was okay for a block to go below that height when performing a swap.
Fixing this will be just as simple as the previous two issues. Go to the Sub-Event which checks for downward swaps, and add this condition:
Condition: BottomBlock>Compare Y Comparison = Less or equal Y = SPAWNY
Your code for this section should now look like this:
Just like the previous condition, this ensures that the swap would not place the block into an area outside the game field. In this case, it looks at the area below the game field.
If you test your game at this point, you should now be unable to make swaps which put the block below the base of the game field.
At this point, we have solved the issues with the swapping system, and can move on to making our points system even better.
2. Floating Points Text
Right now, our points system is pretty effective. It works the way we intended, and already displays everything correctly. Despite that, though, if you gave the game to a player and sat them down with it, they might not be able to tell exactly how many points they were getting from each group they made, since the game can move quickly.
To solve this issue, we are going to add text pop-ups which display how many points the player makes from any groups they form. This will add extra visual flair to the game, and it will make it clear to the player how valuable larger groups can be.
Creating the Text Itself
Before we can start adding the functionality, we need to create a new object which will act as the text pop-up, so follow these steps.
- Go to Layout 1.
- Insert a new Text object:
- Name:
FloatingPointsText
- Layer:
Game Field
- Position:
616, 250
- Size:
127, 43
- Text:
0
- Font:
Calibri, Bold, 24
- Color:
255, 255, 255
- Name:
- In the Projects tab on the right, right-click the FloatingPointsText object, and choose Behaviors.
- Add a new Fade behavior, and close the Behaviors window.
- In the properties on the left side of the screen, change the Fade Out Time to
1.25
.
The object we just created is going to be used to create the floating text that tells the player how many points a given group will give them. Now that we actually have this object, we need to implement it so that when the player makes a match, it will spawn a new instance of the object and change the text to show the appropriate number of points.
Spawning the Text
To spawn the points text we are going to add two new Actions to the NumMatchesFound checks in the FindMatches function.
Go to the FindMatches function, and add these two Actions to the end of each NumMatchesFound>3 check:
Action: System>Create object Object = FloatingPointsText Layer = 2 X = Block.X - Block.Width/2 Y = Block.Y - Block.Width/2 Action: FloatingPointsText>Set Text Text = NumMatchesFound * 10
Your FindMatches function should now look like this:
So what are these Actions doing? The first Action creates the FloatingPointsText
object on top of the first block in the group, and the second one multiplies the number of blocks in the group by 10, just like our points formula does, and sets the text of the new object to that number.
If you run the game at this point, you should notice that the text isn’t moving at all. To fix this problem we are going to add a new Event to our game.
Making the Text Move
Go back to Event Sheet 1 and add a new Event:
Condition: System>Every Tick Action: FloatingPointsText>Move at angle Angle = -90 Distance = 0.25
Your new Event should look like this:
If you run the game now, you will see that the text does move.
At this point, our FloatingPointsText is working the way we want it to, but you may have noticed a slight issue now that the system is in place. The issue itself stems from the way the matching system works, and now that we can see that there is still an issue with matching, we can set about fixing this final issue, and putting our matching system to bed.
3. Completing the Matching System
If you don’t yet know what issue I’m talking about, go into the game, and make a group that contains four blocks. Once your group is made, you should see something similar to what I have in the image below:
As you can see, we actually have two instances of the floating text objects. If you make a group with five Blocks, the issue gets even worse and you will actually see three instances of the points text.
The reason for this issue is based in the way that matches are detected. Right now, our matching system looks at every block individually, and looks in the right-direction, and the downward-direction, to find matches. Because of this, the matching system is actually finding three different sized groups here, even though it is actually just one large group.
The first group will be found when it starts with Block A, and will contain five blocks:
The second group will be found when it starts with Block B, and will contain four blocks:
And the third group will be found when it starts with Block C, and will contain three blocks:
So, right now, our matching system is very inefficient – and broken – since it is checking the same blocks multiple times and registering more groups than there actually are.
How We’ll Fix This
Fixing this issue is actually much simpler than it might seem at first.
The issue here stems primarily from the fact that the matching system has no way of knowing whether the block it’s starting with is actually the beginning of the group. If we could guarantee that we only looked at Blocks which were the farthest to the right, or the highest up, within the groups they belonged to, then the matching system would be effective as-is.
So, all we have to do is add a condition or Event that ensures there are no matching blocks above, or to the left of, the block we start with, and to tell the function when it has performed this check, so that it can proceed normally if the block it’s looking at is the start of the group.
The first thing we will add is a new parameter for the CheckMatches
function. This parameter will be an integer and it will be either 1
or 0
.
If the parameter is 1
, it will indicate to the function that it needs to perform the check to ensure it’s looking at the initial block in the group; if it is 0
, it will indicate to the function that it has already performed this check, and can proceed normally to determine if the group is comprised of three or more blocks.
Let’s Do It
So, start off by going to the FindMatches
function. In this function you call CheckMatches
twice. Since this is the first time you call CheckMatches
for whatever block you are looking at, you need to add a new parameter to each of these function calls and set it to 1
so that it will check to see whether the block it’s looking at is the start of a group.
Your FindMatches
function should now look like this, and I have highlighted the two changed statements for your convenience:
Now that we are telling CheckMatches
when it needs to perform this new check, we need to actually add the new check for it to perform. Go to your CheckMatches
function, and add this new Sub-Event as the first Sub-Event:
Event: Block>Compare X Comaprison = Equal to X = Function.Param(0) - ((Block.Width+2)*Function.Param(3)) Condition: Block>Compare Y Comaprison = Equal to Y = Function.Param(1) - ((Block.Width+2)*Function.Param(4)) Condition: Function>Compare parameter Index = 5 Comparison = Equal to Value = 1
Before you finish modifying the CheckMatches
function you also need to add an Else statement to the top of the original event for the CheckMatches
function, and you need to add the new parameter to the CheckMatches
function call and set it to 0
.
The new code for the CheckMatches function should look like this:
The Event we added does exactly what I described above. First, it looks at the block above, or to the left of, the initial block you pass in.
If that block is the same color as the one you passed in, it does nothing since it knows that the block you passed in is not the first Block in that group.
On the other hand, if it’s not the same color as the block you passed in, the original check occurs because of the Else statement we just added, and it looks for a group of three or more blocks the way it normally would.
If you test the game at this point, and make a group with more than three blocks, you should see only one floating text object telling you how many points that group was worth.
Conclusion
Now that we have finished fixing up all of these features, and we have finally completed our matching system, we are ready to implement the movement system. Since we’ve already done a lot in this tutorial, and since the movement system requires us to make multiple complex systems, I am going to wait till the next article to start the movement system.
If you are anxious to start working on it, consider a few of these things. Obviously the first thing you have to do is implement the movement itself. For that, try using a similar system to what we used when making the points text objects float. From there, start considering how you would change the speed at which they move. Finally, how will you generate new rows of Blocks for the player, and how will you know when to generate new rows?
Take some time to consider these things, and I will see you back here next week for the next big installment of the series.