Congratulations on reaching this chapter! By now, you have learned a lot about Construct 2 and how to use it. You now know about various behaviors and also how to use them through events. You have also learned about expressions and sub-events that are useful when making more complex games. However, there's still one thing missing if you want to create an engaging experience: competition.
Making players compete with their friends is a good way to improve the gameplay experience. One way to do this is to add a leaderboard to your game so that players will fight for the position of the highest score. We will add this element to a space-shooter game. In creating this space-shooter game, you will learn how to create a scrolling background and spawn a new object related to an existing object.
In this chapter, you will learn:
So, just like the previous chapter, we'll start by designing our layout. The sprites used in this chapter can be found under the Space shooter
folder under Sprites
in freebundle.zip
. However, we want to change the default resolution first, because our space shooter will be a vertical one and not horizontal. If you start with a new empty project, then, by default, you'll get a resolution of 854 x 480. To change this, we will simply change the value of the window size in Project Properties. To open the project properties, click on the View link in Project Properties or click on the project name, which is the first item in the Project bar on the right-hand side.
Clicking on this will show the project properties with a lot of configurations that you can apply to your project, such as changing the name and description of the game, choosing what preview browser to use, and selecting the physics engine for the physics behavior, among other things. For now, let's change the window size to 480 x 854. This is the WFVGA resolution, which is a display resolution of 854 x 480, and is approximately the 16:9 display ratio of the widescreen video. This is considered a safe resolution that doesn't crop any of the images. I swapped the width and the height to make it a portrait mode instead of landscape.
As you can see in the layout, changing this property also changes the dotted lines that form our game window to a more vertical shape. After that, add a new background and a playerShip
object. To make the player move, give it the 8 Direction behavior, and we'll also prevent him from moving off the screen with the Bound to Layout behavior. Don't forget to set the 8 Direction behavior's Set angle property to No
because we want it to face upward at all times.
Now, just like any other space-shooter game, we will make the player go forward to the enemy base and destroy all the enemy ships that get in his way. However, actually, the screen doesn't scroll anywhere. The player's ship moving forward is just an illusion; it is the stage that moves backward and makes it look like the player's ship is advancing forward. This is a trick commonly used in game development to make the player move forward. You can either move it forward or move everything else back, and you'll achieve the same result.
So now, create a new layer called Stars and add it below the Main layer but above the Background layer. We created our ship in the Main layer, and we will also create enemies in the same layer. The Stars layer is where we will create the stars that will move backward, or downward in this case, to create the illusion of the player moving forward. To do this, first create a star sprite object and add it in the Stars layer, and then give a Bullet behavior to it so that it can move. You can use the star sprites present in SpritesSpace shooterEffects
. Then, switch over to the event sheet, because we're going to move the stars down using code.
The logic is like this: every half second, we'll create a new star at a random position on the screen, and then, we'll change its angle of movement so that it moves down. We'll also change its speed so that the stars don't move too fast. Translate it into code, and you will get the following result:
If you test the game now, you can see the stars going to the bottom of the screen, creating an illusion of the player moving forward. If, while testing, you move the ship too far to the right-hand side or to the bottom of the screen, you'll realize that the player ship can still go out of the window, while it can't go past the top and the left-hand side of the screen.
What caused this? Didn't we already add the Bound to Layout behavior? Well, it's because we bound it to the game layout, not to the game window. To bind the ship to the window, we'll have to resize the layout to fit the game window. We can easily set this from the layout properties; we need to change the size of the layout to be the same as that of the window.
Now, the player is totally bound to the window.
Next up, we're going to make the enemy, because a space shooter isn't fun without something to shoot at. Add a new sprite object called enemy
and place it on the Main layer. The enemy will do two things: moving and shooting. Moving our enemy object is easy, and it is the same as moving the stars. So, follow those steps again. Now, I'm going to explain how to make the enemy randomly.
We'll create the enemy at a random position every 2 seconds, and after that, the enemy will move slowly downward. So, let's first add a Bullet behavior to our enemy object and change the set angle value to No
. Then, we'll change the speed to 100
to make it move slowly. Next, we'll create the enemy at a random x position onscreen and set the angle of motion to 90
as follows:
Test the game now, and you'll see that we have created the enemies randomly. Next, we'll tell them to shoot.
The word shooting actually means that the enemy will create a new object relative to itself, and the newly created object will move on its own. In this case, we will create a new bullet and shoot it downwards. To do this, we'll have to create two things:
So, let's add a new sprite object as the bullet. We'll name this bullet enemyBullet
to differentiate it from the player's bullet. Before finally adding this bullet by closing the edit image window, we'll rotate this sprite 90 degrees clockwise. The reason we do this is because this object will use the Bullet behavior for movement, and we want to be able to change its angle according to the Bullet behavior's angle of motion. The zero degrees angle of motion refers to the right-hand side of the screen; rotating the sprite will make it easier if you want the enemies to be able to fire in more directions than just one.
Close the edit image window to add the bullet to the layout and put it somewhere off the screen. Another thing we want to do is destroy the bullet automatically after it goes out of the layout, because there's no point in keeping a bullet that we no longer use. We can do this using code, but there's also a behavior for this called Destroy Outside Layout; this will destroy the object when it gets out of the layout. Add this behavior to enemyBullet
.
Next, we'll add an imagepoint to the enemy object. This imagepoint will be the point where the bullet is created or spawned by the enemy. Position the imagepoint in the lower part of the middle half of the sprite. We'll also need to make the enemy shoot the bullet at some interval of time instead of at every tick. So, we'll add a Timer behavior to our enemy object.
The logic to make the enemy shoot is this: when the enemy is created, we'll start the timer to set the interval for each shot and make this timer repeatable. Every time the timer is fired, we will spawn a new bullet at the imagepoint that we created. After that, we'll change the angle of motion for the bullet to make it go downward. So, the code is as follows for the enemy On created
event:
The following is the code for the enemy On timer "shoots"
event:
This will make the enemy shoot every second. If you think the interval is too short, you can change the time the timer is fired at. Test the game now, and you'll see that we have created our enemies successfully.
Test the game now, and you'll see that we have created our enemies successfully.
By now, we have two objects that always go offscreen and are never used again: the enemy and the star. It's a good habit to destroy offscreen objects that are no longer needed, so now, we'll delete them.
We'll destroy the enemy objects when they go more than 100 pixels off the bottom of the screen, and we'll destroy the star objects when they are more than 50 pixels from the bottom of the screen. There's a system's expression called LayoutHeight
that tells us the height of the current layout, and we'll use this to compare the y position of both objects. Look at the following two events:
It's good to have the enemies shoot at us, but without the ability to fight back, the players won't find the game fun; so let's make our player shoot at the enemies. We'll make it a little different than enemy shots; for the player, we'll make it such that the player shoots when they are pressing a key on the keyboard, for example, the Z key.
To do this, we surely need to add a Keyboard object to our project. Then, we'll give a Timer behavior to the playerShip
object. After that, we'll add a player bullet object to the layout and add the Bullet behavior to it. Just like the enemyBullet
object, we'll also rotate this object 90 degrees clockwise. Finally, we'll add a new imagepoint for playerShip
to be the place where the bullet is spawned. After that, our preparation is set.
Now, let's design the logic for player shooting. We will start the timer when the player presses the Z key; we will only check for when the player first presses Z, because we don't want to start the timer at every tick that the Z key is pressed. We will stop the timer when the player releases the Z key; this is to make the shooting stop. The shooting takes place when the timer is fired, and we'll set the timer to fire every half a second. If we write this using code, it will be as follows:
Test the game now, and you will see that the player can now shoot when the Z key is being held down and stops shooting when we no longer press it. Maybe you're asking, "Why don't we use the Keyboard object's is key down
event to check for when the Z key is being pressed and spawn a new bullet if it's true? Isn't it the same?" Well, it isn't. If we use the is key down
event, this event will be true for every tick, and the player's ship will shoot bullets at every tick. This is something we don't want and is something that's hard to control. Using a combination of a Timer behavior and the On key pressed
trigger makes it easier to change the interval of the player's shots.
So, now that both the enemies and the player are able to shoot, let's make the bullets hit them instead of passing through them. To make it look like it's a hit, we'll simply destroy the bullets when they collide with their target. So, we'll destroy the player's bullets when they collide with the enemy, and we'll destroy the enemy's bullets when they collide with the player. However, only making them disappear won't feel right for the player when they play the game; so, let's add two more sprite objects to be shown when the bullet collides and name them playerBlast
and enemyBlast
. Then, let's add the code to show them all:
The code for the On collision with enemy
event is as follows:
Test your game, and you can see explosion effects appear on impact with the enemy:
This seems good, but the explosion effects don't disappear after being called. Let's add a Fade behavior to both playerBlast
and enemyBlast
objects to make them automatically fade until destroyed. The Fade behavior will make the object gradually disappear until it vanishes; the duration for it can be changed from its properties. After that, this behavior can destroy the object after fading out.