Legacy GM How do I pause the game?

Dr_Nomz

Member
Is there a way to stop all code from running (So enemies stop moving, timers stop counting down etc) so the game can be paused? And then a way to resume it like nothing happened?
 
There are many ways to achieve it, though there's nothing inherently built in. You could make the room persistent and go to another room. You could have a global pause variable that exits every event if it's set to true. You could deactivate everything. Just to name a few.
 

NightFrost

Member
If you go with deactivation, it will also be necessary to make a copy of current screen content to surface and draw that to screen while paused. Because when everything is deactivated nothing else will obviously get drawn. And when you deactivate all, you immediately need to follow up with reactivating whichever instance is polling for the unpause button press and drawing the surface to screen. Usually it should be enough to make some obj_pause that does all this stuff.
 

samspade

Member
I'd second the deactivation idea especially if your objects rely on any built in GM variables (thinks like alarms, image variables, etc) as otherwise it is difficult (or impossible) to stop them from running automatically.

A basic version would just be instance_deactivate_all, instance_activate_object(subset) where first you deactivate all instances and then you reactive a smaller group of them - which I normally do through inheritance e.g. instance_activate_object(controller_parent).

A slightly more advance version would be to use a ds_stack, loop through all objects with a with statement, and as you deactivate them, add their ids to an array, then push the array to the ds stack. Then to unpause pop the top array off the stack loop through it and reactivate. This means that you can pause and unpause in layers - e.g. first pause is the game, then you go into a sub menu and pause the main menu, and so on - and you can back up in layers.
 
M

Musehill

Guest
I have an object called Pausable that is the parent of every object that needs to be paused. It only has one variable called paused. That allows me to easily do "with Pausable paused = true;" Then in important events of each child object, I'll simply wrap everything in an "if !paused { }" conditional. With alarms, I will do "if !paused { /*code */ } else alarm[#] = 1" with "#" being the number of the alarm. You can use a script to do something like:

with Pausable {
paused = true;
old_image_speed = image_speed;
old_move_speed = speed;
image_speed = 0;
speed = 0;
}

Then you can reset image_speed and speed to their former values when you unpause.
 

Dr_Nomz

Member
I think I like Musehill's idea best, that actually sounds like the best way to do it.

I'll leave this open so people can post more suggestions, thank you all for your help!
 
I think I like Musehill's idea best, that actually sounds like the best way to do it.

I'll leave this open so people can post more suggestions, thank you all for your help!
I did it that way in my first game and it was a nightmare. Biggest mistake I ever made. Mainly because of having to handle all of the alarms so that they would not count down. The problem with Musehill's idea of setting the alarm to 1 if the pausable value is set does mean that if you paused the game when your alarm was at 35 (for example), when you unpause it the alarm would have counted all the way down to 1 and would then activate in the next step instead of 35 steps later. May not seem a big thing, but what if you are doing longer alarms? They would all count down and then trigger at the same time when they should not be.

The best way is to create a pause object and create that to do whatever you would be doing during the pause (whether it is showing a menu, or whatever). And as everyone else in this thread has said, using deactivation and a surface to show the current screen allow you to capture the screenshot to a surface and draw it, deactivate (pause) all other object instances in the room (which would also freeze any alarms until the instance is reactivated), do what you have to do within the pause object, and when you destroy the pause object just destroy the surface and reactivate all the instances in the room. Simple. There are even loads of tutorials on doing exactly this way, if you look for them.
 

samspade

Member
I would second BaBia Game Studio. You shouldn't manually pause an object if you are using any built in GM variables or functions. It significantly more work to get right, which means it is also easier to get wrong. GM gives you a way to 'pause' objects. It is to deactivate them. This way is incredibly easy to use and the simplest version can be accomplished in three lines of code, one to deactivate all, one to reactivate the portion you care about, and one to reactivate all when you're done. More complicated versions require only slightly more work (I think my pause stack process is two scripts and maybe 15 lines of code total?).

You should really only use the 'manual' pause idea if you need the objects to be active in most ways but not in some (e.g. you want them to run behind your menu system but don't want to be able to interact with them).
 

JeffJ

Member
As someone who uses the approach of manually handling pause states for all objects, I would like to add some thoughts. While it's true that it is more work and easier to get wrong, it also gives you way more control, and gives you more options than a simple menu pause. An example of this - I do not only use it for actual game pausing, I also use it to do special tricks, like a small 0.2 second freeze frame when a big impact happens. What's cool about this is that I can pause exactly the objects I want to, while letting others run, to have maximum control over not only the functionality, but also the aesthetics (example showcased in this blogpost - just Ctrl+F and search for "freeze").

Another thing to keep in mind, is with the deactivation method you often need to rely on drawing everything on screen to a surface. Not only can this become a bit more complicated if you have a bunch of post processing shaders running, but more importantly, it doesn't scale well if your game needs to be future proof in terms of supporting higher resolutions in the future. Our game supports 4K out of the box, but in the future, it would also easily adapt to 8K or whatever else it needs to (provided the user's GPU can handle it, obviously). The bigger the native resolution the game runs at, the bigger the surface that needs to be created, which could cause stuttering, visual artifacts or even crashes, because the size of the surface will always have to scale accordingly.
 
Last edited:

Bentley

Member
As someone who uses the approach of manually handling pause states for all objects, I would like to add some thoughts. While it's true that it is more work and easier to get wrong, it also gives you way more control, and gives you more options than a simple menu pause. An example of this - I do not only use it for actual game pausing, I also use it to do special tricks, like a small 0.2 second freeze frame when a big impact happens. What's cool about this is that I can pause exactly the objects I want to, while letting others run, to have maximum control over not only the functionality, but also the aesthetics (example showcased in this blogpost - just Ctrl+F and search for "freeze").

Another thing to keep in mind, is with the deactivation method you often need to rely on drawing everything on screen to a surface. Not only can this become a bit more complicated if you have a bunch of post processing shaders running, but more importantly, it doesn't scale well if your game needs to be future proof in terms of supporting higher resolutions in the future. Our game supports 4K out of the box, but in the future, it would also easily adapt to 8K or whatever else it needs to (provided the user's GPU can handle it, obviously). The bigger the native resolution the game runs at, the bigger the surface that needs to be created, which could cause stuttering, visual artifacts or even crashes, because the size of the surface will always have to scale accordingly.
Just started reading your article. Love it.
 

Dr_Nomz

Member
I would second BaBia Game Studio. You shouldn't manually pause an object if you are using any built in GM variables or functions. It significantly more work to get right, which means it is also easier to get wrong. GM gives you a way to 'pause' objects. It is to deactivate them. This way is incredibly easy to use and the simplest version can be accomplished in three lines of code, one to deactivate all, one to reactivate the portion you care about, and one to reactivate all when you're done. More complicated versions require only slightly more work (I think my pause stack process is two scripts and maybe 15 lines of code total?).

You should really only use the 'manual' pause idea if you need the objects to be active in most ways but not in some (e.g. you want them to run behind your menu system but don't want to be able to interact with them).
Wait, really? Then what is it? What code, what functions?
 
Wait, really? Then what is it? What code, what functions?
Seriously? Try just looking for deactivate or activate and you will find everything in the manual. But here, try instance_deactivate_all and instance_activate_all. And there are also tutorials as I have mentioned already that deal with pausing if you take the time to look for them.
 

samspade

Member
Wait, really? Then what is it? What code, what functions?
This is the most simplified version.

Code:
///pause
instance_deactivate_all(true);
instance_activate_object(unpausable);


///unpause
instance_activate_all();
You could also do it so that all pausable objects have the same parent and then it would be:

Code:
///pause
instance_deactivate_object(pausable_parent);

///unpause
instance_activate_all();

The stack pauser I mentioned is this:

Code:
///pause
var pause_list = ds_list_create();
with (all) {
    if (object_is_ancestor(object_index, controller_parent)) continue;
    ds_list_add(pause_list, id);
    instance_deactivate_object(id);
}
ds_stack_push(pause_stack, pause_list);
ds_list_destroy(pause_list);


///unpause
var unpause_list = ds_stack_pop(pause_stack);
for (var i = 0; i < ds_list_size(unpause_list); i += 1) {
    instance_activate_object(unpause_list[| i]);
}
ds_list_destroy(unpause_list);
With the appropriate create and clean up events of course. Again this works on having a class that doesn't pause. You could reverse it and instead have a class that pauses as described above.
 

Dr_Nomz

Member
Alright than you for all the help everyone, that looks awesome and I'll play around with it later to see what I can do. :D

But it mentions something about "serious" glitches when used in the draw event? Could someone elaborate on this? (Just curious) Also any tips for how I should be using this? Do's and Dont's and the like?
 

samspade

Member
Alright than you for all the help everyone, that looks awesome and I'll play around with it later to see what I can do. :D

But it mentions something about "serious" glitches when used in the draw event? Could someone elaborate on this? (Just curious) Also any tips for how I should be using this? Do's and Dont's and the like?
I don't actually know. However, you souldn't be using stuff like that in the draw event anyways. The draw events are for drawing not code. For example, draw events run once for every active view. At a minimum this could cause massive lag. It's also possible that due to internal workings of GM, there are other errors.

In general though, don't put any code in a draw event that isn't draw code.
 
Top