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.
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":
This will open the Sprite Editor window where we show the properties for the sprite:
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:
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
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:
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 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)
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:
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:
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):
To add an action from the toolbox, simply click and drag it into the DnD™ workspace:
In this case we want to add the following:
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)
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)
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):
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:
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:
In this event we want to add the following actions:
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:
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:
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:
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:
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:
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:
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:
We then need to add the following to use these local variables to perform our boundary checks. First the left and right check:
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:
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:
The whole event should now look something like this:
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":
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 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:
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.
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:
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:
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:
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:
To add a brick, simply click the object "obj_Brick" and then drag it onto the room to the position you want:
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:
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:
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:
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):
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:
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:
In this event add this Action:
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):
In this event we'll need the following Actions:
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:
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
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:
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:
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:
The next frame should have two arrows pointing down, something like this:
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™:
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:
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):
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:
And here we place this action:
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™:
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!
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!