Legacy GM A Modern Substitute for Sleep Function

A

Anti-Icarus

Guest
In the older versions of GameMaker (the Legacy versions up to 8.1), there was an action in the main2 tab of the object editor called the Sleep action which would have an object pause a game for a set amount of time based on milliseconds (1000 milliseconds = 1 second). Since Sleep is now among the obsolete miscellaneous functions in GameMaker: Studio, I'm looking for a way to have a game pause briefly after completing a set of tasks, like removing a specific number of objects from a room, before moving into the next room. What would be the best way to have the game pause for, say, one second and go to the next room if a number of certain objects is equal to zero in a room the player would be occupying?
 

FrostyCat

Redemption Seeker
Even while it lasted, you shouldn't have used it. A better alternative is to use non-blocking methods such as alarms.

Step:
Code:
if (!instance_exists(obj_something) && alarm[11] < 0) {
  alarm[11] = room_speed;
}
Alarm 11:
Code:
room_goto_next();
This applies to 8.1 as it does to newer versions of GMS.
 
A

Anti-Icarus

Guest
Even while it lasted, you shouldn't have used it. A better alternative is to use non-blocking methods such as alarms.

Step:
Code:
if (!instance_exists(obj_something) && alarm[11] < 0) {
  alarm[11] = room_speed;
}
Alarm 11:
Code:
room_goto_next();
This applies to 8.1 as it does to newer versions of GMS.
Earlier today, I tried out the above method in a textbook game I was working on and it works well. Now the only issue is that the action in the current room continues before moving on to the next room. This could potentially create a few problems, one of them being that of a game breaking bug. Let's assume that you're playing Lazarus, a textbook game that has the player use falling boxes to climb out of a pit to hit the switch in order to proceed. When made in Game Maker 8.1, the game would pause for exactly one second before the room transition could take place. But when made in GameMaker: Studio, what if that player gets killed by a box a half second after hitting the switch before the room transition could take place? The other problem would be that the players would not be able to readjust themselves by immediately transitioning from one room to the next after a round of something like Breakout.

So the real question, or rather the next question, is how can the method described at the beginning here be used to briefly pause the game before transitioning to the next room.
 
My best guess would be to basically update all of your game's crap each frame manually, @Anti-Icarus. Before updating, check to make sure your GameState variable or whatever you want to call it isn't set to "Sleeping" opposed to "MainLoop" opposed to "Paused" (all arbitrary names here.)

In step, do something like "if (GameState == MainLoop), increment animations, move enemies, etc, else if (GameState == "Sleeping"), SleepTimer--;

If SleepTimer==0, GameState =MainLoop;

Yes, it's a huge pain in the ass compared to making your game just sleep for a second, but having your project set up this way will allow you to easily pause your game and do slow motion effects and stuff anyway. Sorry for the 💩💩💩💩ty formatting on this post - on my phone.

Replying to this thread for you directly because you have a rad avatar. ;)
 
Last edited:

FrostyCat

Redemption Seeker
Your next step is to figure out what needs freezing and what freezing means in their context. In Lazarus, the vertical speed of the falling box needs to be set back to 0; in Breakout, the movement speed of the ball needs to be set to 0. In both cases, user input needs to be ignored.

With one-time actions such as setting speeds back to 0, put it in with the code starting off the alarm. For the Breakout example, it may look like this:
Code:
if (!instance_exists(obj_something) && alarm[11] < 0) {
  alarm[11] = room_speed;
  with (obj_ball) {
    speed = 0;
  }
}
With ongoing actions such as stopping user input, you should create a global variable at the beginning of the game, then set it to true upon completing a level and then false again after advancing to the next. For the Lazarus example, run this at the beginning of your game:
Code:
global.level_done = false;
Then for the winning condition check in the Step event (replace winning_condition with the appropriate expression):
Code:
if (winning_condition && !global.level_done) {
  alarm[11] = room_speed;
  with (obj_falling_box) {
    vspeed = 0;
  }
  global.level_done = true;
}
And Alarm 11:
Code:
global.level_done = false;
room_goto_next(); //Next level
Then if you want to stop player input, check !global.level_done before doing what the keystroke is meant to do.
 

YellowAfterlife

ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ
Forum Staff
Moderator
A simple approach would be to have a script that does
Code:
/// sleep_s(ms)
var t = current_time + argument0;
while (current_time < t) { /* idle loop */ }
which will, just as you could expect, freeze the game, but is tolerable so long as not overused.
If you are aiming for Windows only, I'm currently working on a DLL that introduces a function to redraw screen synchronously and a function that has the game wait synchronously, but while still reacting to window events (meaning that the user can drag around or close the game window while this happens if they need to).
 
Top