Legacy GM How can I make the Pause function in my game?

Z

Ziliock

Guest
In game maker 8 it was simply with ATL but in Studio I can figure it out.
 
J

Jordan Robinson

Guest
In Studio, you have to make a pause function from scratch - you could have a variable called isPaused in all of your moving objects, and check this before they are allowed to move. But this isn't very flexible and making changes later on may be difficult. It could work for a small game, though.

I've also seen some people instance_deactivate_all() which will stop everything, and then you can overlay a separate screen that says "paused". If you wanted to still see the game in the background using this method, you would have to use surfaces and draw a "snapshot" of the view just before you deactivated all of the instances.
 

NightFrost

Member
There's several things you need to note when you want to put in pause functionality. You want the exit check as given above on every game object that acts out on screen, but you must also realize that animations will continue to animate and alarms continue to count down independently. You need to bump up all running alarms so they don't fire and zero all animation speeds while game is paused. Because of this, you have to have object's animation speed stored in a separate value you can later retrieve it from.

I do it by first creating the following PauseCheck script:

Code:
if(global.Paused == true){
    for(var i = 0; i <= 11; i++){
        if(alarm[i] > 0) alarm[i]++;
    }
    image_speed = 0;
    return true;
} else {
    image_speed = AnimationSpeed;
    return false;
}
Where global.Paused is the pause flag and AnimationSpeed refers to object' s current animation speed. Then in every object that requires pausing I call at the first line of step event:
Code:
if(PauseCheck() == true) exit;
Why do exit outside the script? Because should the exit command be inside the script, it merely exits the script and continues running the code of the calling object. The exit must be in the main step event code to properly exit.
 
Last edited:

Yal

🐧 *penguin noises*
GMC Elder
You could make the room persistent, then change to another room that acts as the pause menu, and then when you change back, you turn off the room's persistence again. It's not the best overall solution, but it's very easy to set up and pretty useful for games where you have a very advanced menu system.
 
S

Snail Man

Guest
If you want the paused screen to show the game in the background, you could have the game take a screenshot right before leaving the gameplay room, then import and draw it in the pause menu background. Don't forget to programmatically delete it afterwards though!
 
L

L0v3

Guest
The way I deal with pausing is having a pause layer value for every object, similar to a depth value. Then check for every interaction event something like this:
Code:
// Everything above here will be run no matter what.

if (global.pause > pause_layer) exit;

// Everything below here will not be run if paused.
Repition of code will be minimized with proper parentiage of objects, but yes, it have to be implemented for everything. The layering of pause is useful for having UI-Objects ontop of eachother, pauseing the underlying views.
 

RangerX

Member
What I do is the following:

- Take a picture of the game to make a background with. (using "sprite_create_from_surface()")
- Deactivate everything except my Pause Menu object.
- Now you display the picture of the game as background, your menu on top.
- To unpause, I reactivate everything.
- Kill the menu and background.
 
S

SoulTie

Guest
I usually do pretty much exactly what RangerX has suggested with a few minor differences.
1. I copy the application surface to "global.pauseSurface" so that I can deactivate application surface drawing. This helps me boost mobile game performance
2.Use the control object to deactivate everything and then create an instance of oPause.
3. use oPause to draw global.pauseSurface with a blur shader
oPause contains the pause menu. When you unpause the game,
the control object reactivates everything, including application surface drawing, destroys oPause, and frees the pause surface
 
S

sparksinfinite

Guest
If you want a quick (but limited) solution, you can do it with a while loop:

Step Event:
Code:
/// HOLD a button to pause the game

var pause=false;

if (keyboard_check(vk_space)==true)  // or the button you want
   pause=true;

while(pause==true) // infinite loop
   {
   if (keyboard_check_direct(vk_space)==false)
      pause=false;
   }
This causes the game to pause everywhere, because the game stuck at the while loop.

Additionally you can draw something to the screen like "Pause", but this must one step before the step of the while. (the code needs some additions then)

However, this has its limitations, like you can hardly handle user input and delta time stuff must be considered. I would not recommend this method.
 
Last edited by a moderator:
Z

Ziliock

Guest
I usually do pretty much exactly what RangerX has suggested with a few minor differences.
1. I copy the application surface to "global.pauseSurface" so that I can deactivate application surface drawing. This helps me boost mobile game performance
2.Use the control object to deactivate everything and then create an instance of oPause.
3. use oPause to draw global.pauseSurface with a blur shader
oPause contains the pause menu. When you unpause the game,
the control object reactivates everything, including application surface drawing, destroys oPause, and frees the pause surface
Thanks you.Can you translate it to Drag'n Drop or very specific GML(Codes)?
 
Z

Ziliock

Guest
What I do is the following:

- Take a picture of the game to make a background with. (using "sprite_create_from_surface()")
- Deactivate everything except my Pause Menu object.
- Now you display the picture of the game as background, your menu on top.
- To unpause, I reactivate everything.
- Kill the menu and background.
Thanks you!How can I do that in Drag'n Drop? Or GML, but I'm terrible at GML(Codes) a very specific explanation would help
 

Yaazarai

Member
The easiest option is this...

It's super easy to create a pause menu if you use room persistence. The basic idea is that when you pause you set the current room to be persistent and then you change rooms to a "pause room," e.g. a room that acts as the pause menu. Then when you un-pause you change rooms to the room you where in before you paused and then you turn off room persistence.

Room persistence--if you don't already know--tells GameMaker to store everything that's happened in a room in memory so that when you leave the room and come back, the room is just the way you left it.

To do this you'll need 2 things:
  • A global variable to store the current game room.
  • A room that acts as the pause menu.

(Skip step 1 if you do NOT need a screenshot of your game to display behind the pause menu)...
  1. Create a screenshot of the game via the application surface.
    Code:
    // The game always draws to the "application_surface" (see docs for more info).
    var width = surface_get_width(application_surface),
        height = surface_get_height(application_surface);
    
    // This will create a sprite from the application surface, which will be the screenshot of the game.
    global.PauseScreenShot = sprite_create_from_surface(application_surface, 0, 0, width, height, false, false, 0, 0);
  2. Set the current room persistence to TRUE.
    Code:
    room_persistent = true;
  3. Change rooms to the pause room.
    Code:
    global.RoomBeforePause = room;
    room_goto(room_pause);
When you un-pause do this...
  1. Changes rooms to the previous room we where in before we paused.
    Code:
    room_goto(global.RoomBeforePause);
  2. When we've switched to the old room after un-pausing:
    Code:
    // Only run the un-pause code if we actually un-paused.
    if (global.RoomBeforePause != -1) {
        global.RoomBeforePause = -1;
    
        // Only do this if you--skipped step 1--created the pause screenshot of the game.
        sprite_delete(global.PauseScreenShot);
    }
 
Last edited:
S

Soulie

Guest
I usually do pretty much exactly what RangerX has suggested with a few minor differences.
1. I copy the application surface to "global.pauseSurface" so that I can deactivate application surface drawing. This helps me boost mobile game performance
2.Use the control object to deactivate everything and then create an instance of oPause.
3. use oPause to draw global.pauseSurface with a blur shader
oPause contains the pause menu. When you unpause the game,
the control object reactivates everything, including application surface drawing, destroys oPause, and frees the pause surface
I'm looking to use this method to pause my mobile game as I think it might be good for tutorials too. Thanks!

I was wondering, if we are copying the application surface to a different surface (pause surface) then that new surface is volatile, right?
So we'd need to be careful about people going out of the game and coming back on mobiles?

Also :

  • Should we destroy the pauseSurface when we unpause to save memory? Or keep it?
  • When copying the application_surface to pauseSurface, the tiles in my room get placed on top of my other sprites instead of behind them. Any ideas why this might be?
Thanks for any help

*Edit*

I managed to sort out the problem with the tiles. They were getting drawn on top of the whole surface, so they just need disabling too with tile_layer_hide() when showing the pause menu.
Then tile_layer_show() on unpause.
 
Last edited by a moderator:

RangerX

Member
If you don't want to lose your "pause surface" that IS volatile, save your screen as a sprite like my method and not a surface.
Flush your sprite or surface based pause background as soon as the player unpauses.
 
S

Soulie

Guest
Thanks RangerX,

Btw, when you say flush the surface/sprite do you mean destroy/free it from memory?
E.g. surface_free()?
 

RangerX

Member
Yes. If its a surface, use surface_free. If its a sprite, sprite_delete. If its a background, background_delete.
 

Yal

🐧 *penguin noises*
GMC Elder
One approach I use for simplicity sometimes is to deactivate all objects (apart from the pause controller), but also create special 'placeholder' objects for every visible object that also has a sprite, who gets the same sprite, image (but no image_speed), scales, rotation, blend and alpha as the things they're stand-ins for. Uses a lot less VRAM than creating a visual resource on-the-fly, so it might be more compatible or something, too. (It's less effecient when you have more instances, but since they don't actually do anything and GM now skips empty events, it shouldn't be too bad).
 
J

J_C

Guest
The easiest option is this...

It's super easy to create a pause menu if you use room persistence. The basic idea is that when you pause you set the current room to be persistent and then you change rooms to a "pause room," e.g. a room that acts as the pause menu. Then when you un-pause you change rooms to the room you where in before you paused and then you turn off room persistence.

Room persistence--if you don't already know--tells GameMaker to store everything that's happened in a room in memory so that when you leave the room and come back, the room is just the way you left it.

To do this you'll need 2 things:
  • A global variable to store the current game room.
  • A room that acts as the pause menu.

(Skip step 1 if you do NOT need a screenshot of your game to display behind the pause menu)...
  1. Create a screenshot of the game via the application surface.
    Code:
    // The game always draws to the "application_surface" (see docs for more info).
    var width = surface_get_width(application_surface),
        height = surface_get_height(application_surface);
    
    // This will create a sprite from the application surface, which will be the screenshot of the game.
    global.PauseScreenShot = sprite_create_from_surface(application_surface, 0, 0, width, height, false, false, 0, 0);
  2. Set the current room persistence to TRUE.
    Code:
    room_persistent = true;
  3. Change rooms to the pause room.
    Code:
    global.RoomBeforePause = room;
    room_goto(room_pause);
When you un-pause do this...
  1. Changes rooms to the previous room we where in before we paused.
    Code:
    room_goto(global.RoomBeforePause);
  2. When we've switched to the old room after un-pausing:
    Code:
    // Only run the un-pause code if we actually un-paused.
    if (global.RoomBeforePause != -1) {
        global.RoomBeforePause = -1;
    
        // Only do this if you--skipped step 1--created the pause screenshot of the game.
        sprite_delete(global.PauseScreenShot);
    }
This looks like a cool solution. I have one question, didn't you forget to draw the global.PauseScreensShot in the Pause room?
 
Last edited by a moderator:

Tornado

Member
I'm doing like @RangerX.
Deactivating objects and showing the screen shot either via application surface screenshot or via file screen shot depending on whether I want HUD (drawgui) in the screenshot or not.
This works perfect even for physics objects. after unpausing they resume their previous momentum.

The idea with persisting rooms is also nice. Does that also work with physics objects like I described above?
 
Last edited:

Tornado

Member
1. I copy the application surface to "global.pauseSurface" so that I can deactivate application surface drawing. This helps me boost mobile game performance
I would like to understand that, can you please explain it for a surfaces noob? Why do you deactivate application surface? How does it boost performance, I mean we are in pause mode just showing a screenshot, what performance do we boost here?

Where do you draw pause screen, after application surface is deactivated? Why bother?

thx
 
Last edited:
I would like to understand that, can you please explain it for a surfaces noob? Why do you deactivate application surface? How does it boost performance, I mean we are in pause mode just showing a screenshot, what performance do we boost here?

Where do you draw pause screen, after application surface is deactivated? Why bother?

thx
If you're drawing the pause stuff to a new surface then deactivating the application surface won't affect the drawing of the pause stuff (application surface and a surface you create are two different 'screens' so to speak). As to the performance boost, the game will still be drawing application surface if you're simply drawing another surface over the top of it (i.e. the game is basically rendering two screens at once), so deactivating the application surface boosts performance as it removes the unnecessary drawing event. At least, that's what's happening to my limited surface knowledge.
 

Tornado

Member
aha ok, thx for the clarification. I guess the real benefit will be reducing cpu/gpu usage, thus reducing heating and battery consuption for mobile devices.
 
J

J_C

Guest
The easiest option is this...

It's super easy to create a pause menu if you use room persistence. The basic idea is that when you pause you set the current room to be persistent and then you change rooms to a "pause room," e.g. a room that acts as the pause menu. Then when you un-pause you change rooms to the room you where in before you paused and then you turn off room persistence.

Room persistence--if you don't already know--tells GameMaker to store everything that's happened in a room in memory so that when you leave the room and come back, the room is just the way you left it.

To do this you'll need 2 things:
  • A global variable to store the current game room.
  • A room that acts as the pause menu.

(Skip step 1 if you do NOT need a screenshot of your game to display behind the pause menu)...
  1. Create a screenshot of the game via the application surface.
    Code:
    // The game always draws to the "application_surface" (see docs for more info).
    var width = surface_get_width(application_surface),
        height = surface_get_height(application_surface);
    
    // This will create a sprite from the application surface, which will be the screenshot of the game.
    global.PauseScreenShot = sprite_create_from_surface(application_surface, 0, 0, width, height, false, false, 0, 0);
  2. Set the current room persistence to TRUE.
    Code:
    room_persistent = true;
  3. Change rooms to the pause room.
    Code:
    global.RoomBeforePause = room;
    room_goto(room_pause);
When you un-pause do this...
  1. Changes rooms to the previous room we where in before we paused.
    Code:
    room_goto(global.RoomBeforePause);
  2. When we've switched to the old room after un-pausing:
    Code:
    // Only run the un-pause code if we actually un-paused.
    if (global.RoomBeforePause != -1) {
        global.RoomBeforePause = -1;
    
        // Only do this if you--skipped step 1--created the pause screenshot of the game.
        sprite_delete(global.PauseScreenShot);
    }
Ok, so I have used this method and it was so easy and fast, and it works perfectly (for now). I definitely recommend this method for a pause menu.
 

Yal

🐧 *penguin noises*
GMC Elder
When you use room persistence, keep in mind that entering a persistent room gives all objects a Room Start event (even though the room has already "started" way back). If you're not aware of this it can lead to problems later (if you use Room Start to initialize stuff etc). Also, the Room / Instance creation code is not run. Woo, consistency.
 

Tornado

Member
Thx for pointing it out Yal. I never even noticed there is such event.

But I would say it is actually consistent.
The room is created just once, but can be "started" all over again with room_goto. I know the term "starting" can be misleading, but I guess it is hard to find a better term.
Maybe it would be "room enter event" :)
 
R

Richirams

Guest
The easiest option is this...

It's super easy to create a pause menu if you use room persistence. The basic idea is that when you pause you set the current room to be persistent and then you change rooms to a "pause room," e.g. a room that acts as the pause menu. Then when you un-pause you change rooms to the room you where in before you paused and then you turn off room persistence.

Room persistence--if you don't already know--tells GameMaker to store everything that's happened in a room in memory so that when you leave the room and come back, the room is just the way you left it.

To do this you'll need 2 things:
  • A global variable to store the current game room.
  • A room that acts as the pause menu.

(Skip step 1 if you do NOT need a screenshot of your game to display behind the pause menu)...
  1. Create a screenshot of the game via the application surface.
    Code:
    // The game always draws to the "application_surface" (see docs for more info).
    var width = surface_get_width(application_surface),
        height = surface_get_height(application_surface);
    
    // This will create a sprite from the application surface, which will be the screenshot of the game.
    global.PauseScreenShot = sprite_create_from_surface(application_surface, 0, 0, width, height, false, false, 0, 0);
  2. Set the current room persistence to TRUE.
    Code:
    room_persistent = true;
  3. Change rooms to the pause room.
    Code:
    global.RoomBeforePause = room;
    room_goto(room_pause);
When you un-pause do this...
  1. Changes rooms to the previous room we where in before we paused.
    Code:
    room_goto(global.RoomBeforePause);
  2. When we've switched to the old room after un-pausing:
    Code:
    // Only run the un-pause code if we actually un-paused.
    if (global.RoomBeforePause != -1) {
        global.RoomBeforePause = -1;
    
        // Only do this if you--skipped step 1--created the pause screenshot of the game.
        sprite_delete(global.PauseScreenShot);
    }
Hello, sorry i necro this post but i was looking for a way of doing a pause menu and i liked this method, i only have one problem tho, how or where do i change the room's persistance back to false? I ask because in my pause menu i have a button that takes me back to the main menu and then, if i go back to that same room it is still persistent.
 

CMAllen

Member
If you don't want to lose your "pause surface" that IS volatile, save your screen as a sprite like my method and not a surface.
Flush your sprite or surface based pause background as soon as the player unpauses.
Nah. Copy the "pause surface" to a buffer. If the surface is lost, you can regenerate it from the buffer. It's the same effect, but you don't need to worry about extra texture pages and extraneous sprite data floating around. Buffers are non-volatile, so you don't need to worry about them disappearing randomly. You just need to be sure you clean it up at the same time you clean up the pause surface.
 

RangerX

Member
All true. But maybe not worth the assle as having one texture page more while your pause menu is opened will probably not slowdown your game. And the pause menu probably doesn't cause much texture swaps so here again, both solutions are clearly viable.
 
Ok. So I set perstient = false in the object that you click to exit the store. It still works on entry and hangs on exit, That is, the game freezes and turns white.
 
The easiest way is to create a fully opaque pause screen, that way you don't have to worry about making objects "stand still" in the background.
Otherwise, you'd have to mess with the speeds of the objects using variables.

Code:
if global.paused{
image_speed = 0;
speed = 0;
}
would go inside any object you don't want to move while paused.

You'd also have to pause alarms as well.

For the sake of difficulty, I do the easier way.

Create an obj_pause.
In the create event, use a variable:
Code:
global.paused = false; //the game defaults to NOT PAUSED
In a step event:
Code:
if keyboard_check_pressed(vk_escape){ //or whatever key activates the pause screen

global.paused = true;
}

if global.paused{
instance_deactivate_all(true); //this deactivates all objects except the pause screen itself
}

if global.paused && keyboard_check_pressed(vk_escape){ //resume the game

global.paused = false;
instance_activate_all();
}
Finally, in the draw event:
Code:
if global.paused{

draw your pause menu here.

}
If you want other functions available in the pause screen (i.e. quitting the game), you'll have to register those with key presses inside the step event under if global.paused.

If you want background music to stop playing while paused, add audio_pause_sound as well. Then, audio_resume_sound when you're done.
 
There has to be a quicker way than doing a check for a pause variable for every object. I would be doing one hundred checks.Why not use the persistent method? It seems to have worked for some people.
 

Yal

🐧 *penguin noises*
GMC Elder
Let me just point out a thing I noticed.

upload_2018-9-26_19-24-6.png

Please make a new topic instead of necro-bumping an old one if there's not been any replies in 3 months.


If the game crashes (white window + not responding anymore) it's likely an infinite loop somewhere. Check for those, a common one is to put instance_destroy() in the Destroy event (which causes the instance to destroy itself a second time, running the destroy event again - you get the picture).
 
Top