We have done a lot of things in this chapter, and I have explained many things. I am afraid this chapter is a bit hard to understand. Don't give up, and don't stop because we are nearing the end of the chapter. Now that we have added our state-change feature, it is time to apply a losing condition to the game. There are two losing conditions in this game: when the player loses all lives and when the time runs out. To do this, we'll give default values to the global variables related to the losing conditions. We'll give three lives and start the time countdown at 60 at the start of the level, like this:
Then, we'll represent these values on screen like we did in our first game. So, we'll create two new Text
objects to be put on the HUD layer, name them txtTime
and txtLife
, and make their values show gameTime
and life instance variables as follows:
To show that the player has lost, we will display GAME OVER text in large when one of the losing conditions is met. So, create another Text
object called txtGameOver
, add it on the HUD layer, give it the GAME OVER
text, and change the font to make it bigger.
To change the size of a text, we will change the Font property on the Text
object. When you click on the Font property, you'll see a small box with three dots on it; clicking on this will open a window where you can change the font:
In the new window, you'll be able to change the font type, font style, and font size. Set the new size to 36
and put it off screen. We'll also change the color of the text; to do this, click on the Color property of the text, and you'll see a small box on the right-hand side. Click on it, and a box with lots of colors to choose from will pop up. For now, make the GAME OVER text red. Move the txtGameOver
object off the screen, because we will only need it when the player loses.
The first losing condition we want to make is losing by time. The logic is simple: if the gameTime
global variable drops below 1, which can mean 0 or a negative value, then we'll show the GAME OVER text in the middle of the game area. We must also stop the movement of the ball, because we don't want it to keep moving and bouncing around when the player is declared lost. If we write this in code form, it would be as follows:
I want to tell you something about how Construct 2 creates an object. When you want to create an object, this object must already be put in a layout. Any layout is fine; it doesn't have to be the layout that the object is created in. This is because when Construct 2 creates an object, it needs to know the default properties of the object. If it's a Text
object, then Construct 2 needs to know the initial text value, color, font style, font size, and so on. It is advised that you have a separate layout specifically to place objects.
When creating an object, this object must be put somewhere in a layout. It is advised that you have a layout only to store game objects. Another reason to do this is because even off-screen assets in your starting layout will instantiate themselves when the layout started. If you're not careful, you can have a bullet dashed from one side of the screen to the other at the start of the game.
Now, the only thing that's missing is that we still haven't reduced gameTime
; thankfully, Construct 2 has an event that does something every second (or every few seconds, depending on what you want):
Now, we'll make the player lose by life. Players initially have three lives; every time the ball falls below the screen, we'll reduce the player's life by 1, and if the life goes down to 0, we can say that the player lost. The question is how does the game continue after the ball falls below the screen. The answer is: we will create a new ball.
So, the logic is like this: if the ball falls below the screen, we'll reduce the player's life by 1; if it is still above 0, then we'll create another ball to continue playing; and if it is 0, then the player loses. So, this is going to be as follows:
If you test it now, the game should be working as we want it to. However, there's still one thing missing: the score. So, let's make this.
Calculating the score is really easy because we already have an instance variable in the blocks
object that we can use to increment the score when it's destroyed. So, we'll basically just add the score
global value every time a block is destroyed:
Here, we will make a new block, an On destroyed
event, besides the previous one we made. It's okay to make several events, which are the same as this one; this can be used to chop down the number of actions in an event to make the code easier to read and understand.
After we have made the code, it's time to show the score. We'll show it when the level ends, that is, either the player wins or loses. We'll create a new Text
object called txtScore
on the HUD layer, and we'll put it off the screen somewhere. First, let's show this object when the losing condition is met. Create a new txtScore
object when either gameTime
is below 1
or when the player's life is equal to or less than 0
. So, we'll add an action to two events.
After creating the text score object, we will make it show its initial value. This initial value is not the one we set in its Properties bar, but will be based on the score global variable. As a result of this, we'll create its initial value at another place when it is created. Construct 2 has an On created
event that fires when an object is first created; we'll set the initial value there:
Test the game now. You'll see that the Score textbox shows up along with the GAME OVER text when the player's life is 0. Next, we'll show the score when the player wins.
A player wins this game when all the blocks in a level are destroyed. To know whether all the blocks have been destroyed or not, we will count the number of instances of the block. If it's 0, then we know that all the blocks have been destroyed. Construct 2 has an expression to count the number of instances of an object; to compare an expression instead of a variable, we'll use the system's compare two values
event, and create a condition "System blocks.Count = 0"
.
Also, we only want to count the blocks when the game is going on, not after the game is over. So, we'll add another condition that will serve as a marker when the game is over. We want to stop the movement of the ball after the player wins, so let's use this as a marker and set the ball's speed to 0
. We'll stop the ball's movement when the player wins; with actions and conditions combined together, our code will look like this:
Play the game until you win, and you can see that the score is shown as we wanted it to. The ball has also stopped moving, so we don't have to worry about it falling below the game area after we win.
Well, we've got a perfect working small game. Awesome, right! However, just like any other game, this one potentially has bugs. There are two bugs here: the timer doesn't stop when the game ends, and the timer can count down to below 0. We can fix the first bug by making sure that we only subtract the gameTime
variable while the game is still on, in other words, when the player's life and number of blocks are more than 0.
The second bug is fixed simply by changing the text value when gameTime
is less than 1
. The resulting code is as follows: