Breakthrough | DnD


Breakthrough | DnD

Welcome to the BreakThrough tutorial! This tutorial is designed to get you up and running using GameMaker Studio 2 in as short a time as possible and will take you through the steps required to make a "breakout" style game. In this tutorial you'll be making a basic but playable version of the game from scratch using DnD™ (Drag and Drop™). Should you prefer a more textual approach to game making, this tutorial is available using the GameMaker Language (GML) on this page

BreakThrough Final Game


Sprites

When using GameMaker Studio 2, all your visuals start off as sprites. These are simply images made up of pixels that we will draw to the screen to represent what is happening, and in the case of a "BreakThrough" game, we will need the following:

  • A bat - This will be what the player moves to direct the ball

  • A ball - This will bounce around the screen and destroy bricks

  • Bricks - These are what you must destroy to complete the game

  • Borders - What the ball will bounce off so it doesn't go out the screen

To create a sprite, go to the Resource Tree, then use the Right Mouse Button on the Sprite resource and select Create Sprite, then name the sprite "spr_Bat": 

Create A Sprite

This will open the Sprite Editor window where we show the properties for the sprite:

The Sprite Editor

The first thing we need to do is make the sprite the correct size, as we don't want a square bat! For that click the Resize Sprite button and change the size of the sprite to 64 pixels wide by 16 pixels tall:

Resize Sprite Canvas

Back in the Sprite Editor again, click on the Edit Image button to open up the Image Editor. The Image Editor is used in GameMaker Studio 2 to draw and edit all the graphical assets that make up your game. In this case we want to draw a "bat" for the game, so, use the different tools in the toolbox to do this now, specifically:

  • The Fill tool : Fill the canvas with a colour

  • The Rectangle tool : Draw an outline around the canvas

  • The Eraser tool : Remove the corners to give the bat a "rounded" look

Make The Bat Sprite

You can take a moment if you wish to play around with the other draw tools (you can find full descriptions for each of them in the manual) to see what they can do or make the bat image prettier, then when you are finished simply close the image editor and the image will be saved and assigned to the bat sprite.

We need to set the sprite origin now. This is the point where the sprite will be positioned within the room (think of it like pinning an image to a board... the origin is where you stick the pin) and we need to set it to the Middle Center position:

Set The Sprite Origin

With that done, let's make the rest of the basic sprites for the game, starting with the bricks:

  • Create a new sprite and call it "spr_Brick"

  • Click the "Resize" button and set the size to 32 width and 16 height

  • Click the "Edit Image" button and in the image editor fill the rectangle with white and give it a black border (we are going to colour the bricks programmatically so they need to be black and white)

  • Close the Image Editor and the Sprite Editor, without changing the origin of the sprite as it's fine set to the top left

The Brick Sprite

The next sprite to make is for the ball, so go ahead and do the following:

  • Create a new sprite and call it "spr_Ball"

  • Click the "Resize" button and set the size to 15 width and 15 height

  • Click the "Edit Image" button and in the image editor draw a filled circle of any colour. You can do this freehand or use the Ellipse tool

  • Close the Image Editor, and in the Sprite Editor set the origin to the Middle Center (like we did for the bat sprite)

The Ball Sprite

Okay, that's all the sprites for now. Let's move on to creating some objects to use them!


Objects

We are now going to make our game objects. Objects are the resource that we use to control aspects of a game and to do specific things. They can be given a sprite, have behaviours, and they can be instructed to react to certain game events as well as to each other.

So, let's make our first object! This object is going to be for the "bricks" that we want our player to break. To create this, go ahead and right-click on the Objects resource in the resource tree and select "Create Object". This will open up the Object Editor:

The Object Editor

In the "Name" section give the object the name "obj_Brick", then click the button labeled "No Sprite". This will open the Asset Explorer where you can select the brick sprite that you drew previously:

Adding A Sprite To An Object

We don't need to change any other properties for this object, and can now move on to adding some Events. An Event is simply a moment within the game loop when something happens. The main ones are:

  • Create: This is triggered the first time an instance of the object is created in a room and is where you would initialise variables and set values etc...

  • Step: Each game step (or frame) this event will be triggered, and it's where you would place the majority of the objects logic

  • Draw: This is where things are drawn. If you have no code in this event, then GameMaker Studio 2 will automatically draw whatever sprite is assigned to the object

  • Destroy: This event is only triggered when an instance of the object is destroyed (removed from the room) and can be used for a variety of tasks like creating an explosion, or adding score, or playing a sound, etc...

For more detailed information on all of the events that an object can have, please see the manual.

In the case of our brick object, we will need to use the Create Event only (for now), so in the Event window, click the Add Event button and select Create. This event will now be added and a DnD™ workspace will open up ready for you to add your actions to it (actions are the individual "blocks" that will be used to create the game code, shown by category in the Toolbox on the right of the image below):

Brick Object Create Event

To add an action from the toolbox, simply click and drag it into the DnD™ workspace:

Add An Action

In this case we want to add the following:

Brick Object Create Event Actions

The first action there is the Choose action (from the Random category in the Toolbox), which permits you to add various options from which one will be chosen at random. The chosen option is then stored in a temporary local variable so it can be used to set the image_blend of the instance sprite (image_blend is a built-in variable that controls the colour to be blended with the sprite). In this case we are telling GameMaker Studio 2 to choose randomly from one of six colours, and this will make our brick instances all different colours when they are created in a room.

With that done, you can close the Object Editor for the brick, and we can move on to creating the bat object...


Bat Object

Now we'll create an object for the player to control, and in this case it's going to be a "bat" that will be used to bounce the ball back up the screen. For this, you need to:

  • Create a new object (use the right mouse button on the Objects resource and select "Create Object")

  • Name the object "obj_Bat"

  • Assign the object the sprite "spr_Bat" (click the button with "No Sprite" and select "spr_Bat" from the asset manager)

The Bat Object

We'll also take a moment to create the Ball object. We won't be doing anything with it yet, but we need it to exist because we'll be applying actions to it later in the Bat object:

  • Create a new object (use the right mouse button on the Objects resource and select "Create Object")

  • Name the object "obj_Ball"

  • Assign the object the sprite "spr_Ball" (click the button with "No Sprite" and select "spr_Ball" from the asset manager)

The Ball Object

Go back to the Bat object now, and add a Create Event (click the Add Event button and select Create). In this Create event we'll add the following action to create a new instance variable, spd (from the "Common" category in the toolbox):

Set A Variable For Speed

This variable will be used to control the speed of movement for the bat. We also need to store the x offset value for the bat sprite, as we'll be using that to ensure that the bat doesn't go out of the screen when it moves left or right (the x offset value is the x position of the sprite origin). There isn't a dedicated DnD™ action for this, so we'll use the Function Call action (from the "Common" category) to call some GML, like this:

Get The X Offset Value

This GML function will get the X offset value and then the action will store it in the variable xoffset for later use.

This object will also need Keyboard Events to check for keyboard input. Note that there are actually three types of Keyboard event: the Down event - which is triggered continuously while a key is being held down, the Pressed event - which is triggered once when a key is initially pressed down, and the Up event - which is triggered once when the key has been released. Go ahead and add a Keyboard Down Event for the Left arrow key now:

The Key Down Left Arrow Event

In this event we want to add the following actions:

Move Left

Here we use the If Variable action along with the Else action (both from the "Common" category) to check "if the x position is greater than the spd plus the xoffset, add the spd value on to x, else set the x position to the xoffset value". This check simply ensures that the bat will only move left as long as the sprite is within the room bounds.

We need to do the same for moving right now, so add a Keyboard Down Right event to the object and give it the following actions:

Move Right

This does the same as the Left Down event, only now we are checking to see if the bat, when moving to the right, will go outside the width of the room (room_width is one of many built-in variables available to get room information).

We need to add one final event into this object, and that's a Step Event. The step event is called every "step", or frame, of the game, so any actions added here will be run continuously. We need to use this event to ensure the ball object "sticks" to the bat when moving left and right until the player decides to start the game.

Add the Step Event now (not the Begin or End events, but the general Step event) and give it the following actions:

Move The Ball With The Bat

Here we create a temporary local variable to hold the unique ID value of the Bat instance, then we use the Apply to... action to tell GameMaker Studio 2 that the next actions are to be applied to the Ball object. The next actions have the ball object chack a variable and if it is false move the ball to the same x position as the bat.


Sound Effects

Before we continue on to fill in the details of our Ball object, let's take a moment to add some sound effects to our game.

We're going to add three sounds: a bounce sound, a break sound and a button sound. To start with, go to the resource tree and right click the "Sounds" resource and select Create. This will open the Sound Editor:

The Sound Editor

Name the sound "snd_Bounce" and then click file explorer button and browse to an appropriate sound (it should be *.wav or *.ogg format) then add it. We don't need to change any other settings here, so close this window.

Now create two more sound resources and name them "snd_Break" and "snd_Click" and add appropriate sound files to them.

With that done, we can move on to creating the ball object.


Ball Object

We created the Ball object previously, but we haven't added any events to it. Let's remedy that now by adding a Create event, to which we'll add the following actions to set up some variables:

The Ball Object Create Event Actions

This object will also need a Keyboard Down Event targeting the Space key, so we'll add that now and give it the following actions:

The Ball Object Space Key Down Actions

All we're doing here is in the event that checks to see if the "Space" key has been pressed down, we check to see if the go variable is set to false, and if it is then we play a sound and then set the ball in motion, setting go to true again so it only happens once.

That'll set our ball in motion, but what about when it reaches the edges of the game area? If we don't stop it, then it'll fly out the game room, which isn't really much fun! To prevent this we'll detect when the ball is in a collision with the room boundary and react accordingly. Luckily for us, in the Other event category we have the Intersect Boundary event:

The Intersect Boundary Event

First we need to define a number of local temporary variables to hold various different instance variable values. You could just use the instance variables directly, but we'll assign them to local vars instead as it's easier to remember and keep track of:

Define Local Instance Variables

We then need to add the following to use these local variables to perform our boundary checks. First the left and right check:

Check For Left Or Right Room Boundaries

These actions check to see if the bat bounding box has left either side of the room, and if it has it reverses the horizontal speed (making the ball "bounce") and then sets the it to a position that keeps it perfectly within the room. We'll do something similar for the top and bottom of the room now:

Check For Top Or Bottom Room Boundaries

These actions will check to see if the ball is about to exit from the top of the room and then reverse the vertical speed accordingly, except if it goes out the bottom. In that case, the ball instance will be destroyed and a new one created.

The final section of DnD™ that we need to add will play the "bounce" sound we added earlier, and then also add a small random amount between 2 and -2 to the direction of the ball. This is to prevent the ball possibly getting "stuck" bouncing at perfect 180° angles between the wall and anything else. We will also increment the speed of the ball a little bit, which will increase the difficulty of the game as it progresses:

Play Bounce Sound And Set Speed And Direction

The whole event should now look something like this:

Full Action List For The Boundary Event

NOTE: The above is split into two columns to make it easier to read, but actually forms a continuous chain of actions.


Collisions

The next piece of DnD™ code required for the ball will go in a Collision Event. A collision event is triggered when the object with the event comes into collision with the instance of another object which you specify. In this case, we are going to add a collision for the ball with the brick object, so click the Add Event button now and add a Collision event with the object "obj_Brick":

Ball And Brick Collision Event

And in the DnD™ editor we will add some GML code. This is because we are going to use the lengthdir_x() and lengthdir_y() functions along with move_bounce() to ensure a proper "bounce" from the brick. So add the Execute Code action with the following:

The Execute Code Action

The ball will be moving at a speed of more than 1 pixel every game frame, so when a collision is detected it will probably be when the ball and the brick sprites overlap. The code above simply moves the ball back along the direction it came from until the sprites no longer overlap, and then it calls the move_bounce() to tell GameMaker Studio 2 to "bounce" the instance (GameMaker Studio 2 will do all the maths for you and set the speed and the direction of the ball as appropriate).

With that done we need to increase the speed of the ball speed - ensuring it doesn't go over a a maximum speed value - then play a sound and destroy the brick. We'll do that using the following DnD™, which you should add after the Execute Code action:

Bounce The Ball

Note that we change the scope of Destroy Instance to target the "other" instance in the collision (the brick). If we don't do this, we'll destroy the ball instead.

Destroy The Other instance In A Collision

When a collision event is triggered it is because the sprite bounding-box of one object is overlapping the sprite bounding-box of another, which in this case means that the ball is overlapping the brick. We want to simulate a bounce off the edge of the brick, but if they are overlapping (even if it's only by a couple of pixels) then this bounce will be wrong, so what this code does is it first moves the ball back along the direction it came from until the bounding-boxes of each instance in the collision are no longer overlapping (they could be considered "touching") and then uses the a GML function to calculate the bounce direction, before destroying the brick itself and playing a sound.

Our final piece of DnD™ will go in another Collision event, this time with the Bat object. So, add a Collision event with "obj_Bat" and give it the following actions:

Bounce The Ball Off The Bat

With these actions we are setting the direction of the ball based on how far from the center of the bat the ball hit, so in this way we are giving the player a bit of control over the direction of the bounce.

It's time now to place all this into a room and test our game!


Rooms

When making a game in GameMaker Studio 2, it requires at least one room to run, and so GameMaker always adds a room to your new projects. In this case it's called "room0" and can be found in the Resource Tree Rooms section. Like all other resources, you can add further rooms by using the right mouse button menu and selecting "Create Room", but for our game, we'll only need one so let's just edit that.

To start with, double click on the room in the resource tree to open the room editor:

The Room Editor

Everything that you place into the room is placed onto a layer, and you can see that there are two layers pre-created for you - one for "Instances" and one for the "Background". You don't need to add any other layers as these are fine for what we're making, so click on the "Instances" layer to select it ready for adding our game objects to.

NOTE: It's important to understand that you don't actually place objects directly into the game rooms, but rather you place instances of these objects which are basically copies (or clones if you prefer) of the object resource. So, in a typical game, all the characters, monsters, balls, walls, etc... are all objects you create in the resource tree, which you then place as an instance in the Room Editor. This instance can then be changed in the room editor itself or through code, so that it can be scaled, or coloured, or have other details modified from the "base" object. So when we talk about something affecting or changing an instance, we mean it affects that one particular copy of an object in a room, but, when we talk about affecting or changing an object, we mean that we are modifying the object in the resource tree and anything we do to it will be reflected in all the instances created from that point on too. So, the object is the template for the instance, and the instance is what we place in a room to make our game. 

To start with, lets make the room a little smaller. The default size is a playing area of 1024x768 pixels, but we want to set it to 640x480. This is done from the Room Properties tab:

Changing The Room Size

We now want to place some brick instances into the room. To make things easier, you should set the editor grid to be 32x16 rather than 32x32:

Grid Settings

To add a brick, simply click the object "obj_Brick" and then drag it onto the room to the position you want:

Add Bricks To The Room

It can be time consuming to constantly drag instances of objects from the Resource Tree, so instead you can simply select the brick object and then "paint" it into the room by holding down and then clicking and dragging where you want:

Paint Bricks In The Room

Add about 6 layers of bricks, and then add a single instance of the ball object and then a single instance of the bat object. Your room should now look like this:

The Finished Room

Time to test the game out!


Gameplay

The time has come to test our game! This is the easy part as all you're required to do is press the "play" button at the top of the GameMaker Studio 2 IDE. If all has gone correctly, your game will run and you can play it using the "Space" key and the Arrow keys:

Finished Gameplay

This is a great start, but it's missing a few things to make it a "complete" game - namely player lives and a score. We want the game to give you three "lives" and keep track of the score you get from each brick destroyed, so for that we are going to make a controller object (A controller object is simply an object in your game that is designed to control the things that go on in the background, and it usually doesn't have a sprite assigned to it although it can have, and it can also draw stuff independently as we'll see).

Before adding the controller however, let's add a Font resource, as we'll want our controller to draw some text to the screen later. To add a font, simply right click on the Fonts resource and select Create Font. In the font window that opens, name the font "fnt_Game" and then select something that you think will look good, setting the size to 20 (or whatever seems appropriate for the font being used):

Adding A Font Resource

You can close the Font editor now.

For our controller you will need to create a new object, call it "obj_Control", and then add a Create event with the following Action:

Create The State Variable

We'll be using this variable to set the "state" of the controller so that it knows whether the game has to start, is being played, or is finished. Apart from this, we'll also use the Game Start event to initialise some global variables:

The Game Start Event

In this event add this Action:

Initialise Global Variables

These global variables will permit us to keep track of important values without having to worry about which instance of an object is accessing them or changing them, and by initialising them in the Game Start event, they will only be initialised once even if we restart the room (but if we restart the game they will be reinitialised).

We now need to draw the score and lives of the player to the screen so you'll need to add a Draw event to the object. Note that - like the Step event category - the Draw event has a number of different event types that can be used, but for this game simply use the regular Draw event (you can find out more about the different draw events from the manual):

Add A Draw Event

In this event we'll need the following Actions:

Draw Global Game Variables To The Screen

Here we are drawing the score across the top of the room, and then a series of sprites (scaled down) to represent the player lives at the bottom.

We need to add one final event to this controller object, a Step event. We'll be using this to restart the room when the player destroys all the bricks. Add this event now, and give it the following Actions:

Check If The Game Is Over

Here we'll either be restarting the room when all the bricks are gone (and because we are using global variables, this will not reset the score or lives), or we'll wait for the player to restart the room if all the lives are gone, resetting the global variables.

Now that we have that done, and before continuing on to do anything else, open the Room Editor and add this object into the game anywhere then close the room editor again...

We'll test this in a moment, but first we need to add a few extra Actions to our object "obj_Ball", so open that now.

We need to calculate the score and tell the controller object when the player has a lost a life, etc... so to start with we'll edit the Collision event with the brick object so that it adds to the global score variable. You want to add the following Action after all the others

Add To The Player Score

We also need to modify the Intersect Boundary event, in the section where we check if the ball goes out the bottom of the room, where the Destroy Instance action is. Here we need to expand it to do a bit more than just destroy and recreate the instance, so change it to look like this:

Ball Leaving Room State Check

Go ahead and play the game now! If all has gone well, you should see intro text on the screen, a score that changes as you play, lives as markers along the bottom and the game should change according to whether you have no lives left or you destroy all the bricks.


Powerups

The way our BreakThrough game is right now, you could probably consider it finished, and it is to a certain extent, but it's missing one final thing to make it into a "proper" BreakThrough game... powerups! So we're going to add them now.

To start with, create a new sprite and set the size to 32 width and 16 height and call it "spr_PowerUp". Open the sprite in the Image Editor and draw two arrows, something like this:

Expand Bat Icon

We're going to add another image to this sprite to be used in a second powerup type. For that click the large "plus" icon to create another frame:

Add New Frame

The next frame should have two arrows pointing down, something like this:

Slow Down Ball Icon

Now create a new object and call it "obj_PowerUp". Assign it the sprite we've just made, then add a Create Event with the following DnD™:

Power Up Create Event

These actions will select a sprite frame to use for the powerup and set it moving down the screen. We need to remove the instance from the game if it is no longer visible, so the next thing to add is an Outside Room event (from the Other category) with this action:

Power Up Outside Room Event

Finally, we need to add a Collision Event with the object "obj_Bat". In this event we're going to have the game change based on the image index (frame) of the sprite that the powerup uses. In this case, frame 0 will make the player bat larger, and frame 1 will slow the ball down. The action to do this are as follows (and should be added to the event):

Power Up Collision With Bat Event

With this DnD™, if the powerup uses frame index 0 then we set the player controlled Bat object to scale along the x-axis (stretching it), or if the frame index is 1 we set the ball speed back to it's original speed. Note that if it's frame 0 we also call an Alarm Event in the player object. This event won't run immediately, but will instead count down for 10 seconds before running (our game has an FPS of 60, so room_speed equals 1 second of time).

Let's add that Alarm event now, so open up the object "obj_Bat" and add an Alarm[0] event:

The Alarm[0] Event

And here we place this action:

The Alarm[0] Event Of The Bat

The last thing we need to do for the game to be finished is have the Brick objects spawn one of the powerups. So open up the object "obj_Brick" and give it a Destroy Event with the following DnD™:

Spawn A PowerUp

Press the Play button now to see the game running... And then give yourself a pat on the back for having created a complete game in virtually no time!


Summary

If all has gone well, you should now be playing a your own, complete, version of BreakThrough!

BreakThrough!

Now what? Well, you have a firm base on which to build so why not take some time to try things out based on what you've learned so far? Here are some suggestions for you:

  • Add more sounds - We should have a sound for when the ball leaves the room and also for when the player gets a powerup, so why not add them?

  • Add more powerups - Adding more powerups should be fairly easy now. Add a new image to the powerup sprite, add the frame number into the Choose action within the create event, then edit the Switch action within the collision event to do something. Maybe have one to make the bat smaller? Or try making one which has the ball pass through and destroy bricks rather than bounce off them?

  • Add a background - The game is played over a simple black background, by why not add your own colourful one? You'll need a 640x480 sized sprite and then set it in the Room Editor to the Background layer.

  • Make proper levels - At the moment the game is played on a single level that regenerates, but why not try making custom levels? You'll need to make more rooms, add the instances to them, and then in the controller object set it to go to another room instead restarting the current one when no bricks are left.

Those are just a few things that you can do with a base like this, but there is so much more! You could try adding a title screen and menu, or making a pause mechanism, or even adding persistent leaderboards and achievements... The list could go on and on, but the important thing is that you learn how to make games using GameMaker Studio 2 and, above all else, you have fun doing it!