Hello, and welcome to another GameMaker basics tutorial. Today, I want to talk to you about how to pause your game. It is a fairly simple process, but it can be a bit confusing if you are unfamiliar with certain GameMaker functions.
Pausing is simply the act of stopping, or freezing, the objects in your game. The code stops running in the object when paused, and picks back up when unpaused. There is a very handy GameMaker function called instance_deactivate_all(); that will make this easy for us to manage. This particular function will essentially turn off all of your game objects. The objects are not deleted, but they are no longer shown on screen when deactivated. When we need to unpause we simply call the function instance_activate_all(); to turn everything back on.
The easiest way to manage pausing (and lots of other global game related things) is to do so from a Game Controller. No, I don’t mean an Xbox controller! I mean an object in your game that acts as the overseer for all other objects, game states, score, screen size, pausing, etc etc. Let’s start by creating that object. I prefer to keep the name of the object as short as possible, since you may be referring back to it often from other objects. I’m going to use oGame for this example. Create a new object, name it oGame, and add the Create Event. Inside the Create Event, we need to initialize some variables.
paused = false;
screenShot = -1;
The paused variable is simple enough. Its a boolean (a true/false) that we will use to trigger the pause/unpause state. The other variable, screenShot, will be used to store the index (in GameMaker an index is a number that points to a resource like a sprite or object) of a sprite that we will be creating later. For now you can ignore it.
Go ahead and add the Step Event to your oGame object. This is where we will set up the button press to pause and unpause. Let’s add a few lines of code.
paused = !paused;
The first if statement simply flips the paused variable when we press the spacebar. By using the exclamation mark operator in front of a variable, we are essentially calling the opposite of the variable. paused = !paused will set the paused variable to the opposite of what it currently is. Since our variable is a boolean, it is set to true or false.
The second if statement is what deactivates, and reactivates, all of our objects based on whether or not the paused variable is true or false. You’ll notice that I’ve placed a one in the instance_deactivate_all(); function. That is because instance_deactivate_all(); needs to know if it should deactivate the object that is calling the function. In this case, our oGame object is calling the function. We don’t want that object to be deactivated, as it is the object in control of pausing. If it were deactivated we couldn’t unpause the game. If a zero were provided instead of a one, all objects, including the object calling the function, would be deactivated.
On the flip side of instance_deactivate_all(); we have instance_activate_all();. This function will activate any object that has previously been deactivated. It does not require any arguments or additional information.
Now let’s test this out. Go ahead and create some objects, give those objects a sprite, and place them in your room. It doesn’t matter if the objects are moving or running any sort of code. We need them to verify that our code is working. Once you’ve placed your new objects in the room, along with your oGame object, go ahead and run the game. If everything was set up correctly you should see your objects disappear and reappear when pressing the spacebar.
Additionally you may want to draw some text on the screen letting players know that the game is paused. Add the Draw Event to your oGame object and add the following code.
draw_text(view_wview * 0.5, view_hview * 0.5, "Paused");
The first line will align our text to the center.
The if statement will draw the word “Paused” at the center of your screen while the paused variable is true. You could also draw your pause menu here, or draw a background behind the text if you wanted to.
But what if you wanted to keep drawing all of the objects on the screen that were deactivated? Well, that is slightly more advanced.
Slightly more advanced setup
Alright, this is where things can get a little bit tricky. We already set up the variable we needed for this setup. Remember the screenShot variable? Now we are going to use it. What we want to do is take a screenshot of the screen when pause is pressed, draw that screenshot to the screen while paused, and then delete the screenshot when we unpause. This can be especially tricky if you are unfamiliar with surfaces in GameMaker, so here is a quick crash course on surfaces.
A surface is like a canvas you are drawing on. Whenever you start a project in GameMaker, you are automatically drawing to the application surface, which is really just the default surface. If you wanted to you could draw to additional surfaces to achieve different effects. For now all we need is the application surface, and that is already provided for us.
Open your Step Event code in your oGame object and make the following changes.
paused = !paused;
screenShot = sprite_create_from_surface(application_surface,0,0,view_wport,view_hport,0,0,0,0);
The first addition is in the keyboard check statement. We check to see if NO sprite exists by checking our screenShot variable, which is set to -1 when initialized. If that particular sprite does not exist, we create a new sprite based on the application_surface and store it in our screenShot variable. The function used is sprite_create_from_surface(); and as you can see it requires a lot of arguments. You can see that we are addressing the application_surface to take a screenshot.
Check out the handy dandy table from the GameMaker Studio documentation for information on each argument.
Quick side note about assets and their indexes. An asset in GameMaker is a sprite, background, sound, room, path, font, or timeline. When an asset is created, it has an index assigned to it. Indexes are always positive numbers! So when we check to see if a sprite exists, as we did above, we are really checking to see if there is a sprite asset with that particular index. Since our screenShot variable had a negative number, there is no way it could have been an existing index.
The second addition made is to the unpause portion of our second if statement. We check again to see if a sprite exists, only this time if it does exist we delete it. If we didn’t delete the sprite we created we would very quickly run out of compute resources and everything would crash! Creating sprites on the fly like this is very expensive in terms of compute resources!
Finally, open up your Draw Event in the oGame object and let's draw the screenshot we captured. Only one line needs to be added.
draw_text(view_wview * 0.5, view_hview * 0.5, "Paused");
If you are unfamiliar with draw_sprite_ext();, click here to read a blog post I’ve written that explains it in great detail. Now, just a heads up if you run the game and your screenshot isn’t being drawn correctly to the screen. The x and y scale of the screenshot needs to be relative to your x and y viewport. In my example above, the viewport is the same size as the view itself, so it is a one-to-one scale. If your viewport is twice the size of your view, then you will need to reduce the scale to 0.5, and so on.
If everything was set up correctly you should have a functional pause/unpause feature that draws everything to the screen! This is definitely not the only way to set up pause/unpause in your game, but it is a great starting point.
That's it for this entry! I hope you learned something and put this new knowledge to good use. You can follow me on Twitter and on my website for more gamedev related stuff.
Nathan Ranney is the founder of punk house game dev shop, RatCasket. He’s best known for the creation and development of Kerfuffle, an online indie fighting game.