GML Step event = false?

S

Schoolboyz

Guest
Is it possible to make it where if a certain situation happens, the step event becomes false until alarm[0] is done? I want to make the player have an automatic idle animation play when the level beings, and then after the alarm is done, all normal gameplay returns.
 
C

captainlionbug

Guest
Create a variable, for example "playerFrozen", and active it when you set the alarm, then in the step event put if !playerFrozen { the whole step event}, then when the alarm happens you set playerFrozen to false. That's how I do it, in my case it's a global variable, because whenever I want the player to not move I just activate it from whatever instance I want.
I hope that helps!
 
S

Schoolboyz

Guest
Create a variable, for example "playerFrozen", and active it when you set the alarm, then in the step event put if !playerFrozen { the whole step event}, then when the alarm happens you set playerFrozen to false. That's how I do it, in my case it's a global variable, because whenever I want the player to not move I just activate it from whatever instance I want.
I hope that helps!
I tried your method but unfortunately it didn't work :(
Variable in create event:
Code:
global.frozen = true;
Alarm code:
Code:
global.frozen = false;
Step event code:
Code:
if global.frozen = true
    sprite_index = Metal_Idle
    {
        image_speed = 10
        alarm[1] = 100
    }
    
if global.frozen = false
{
"long unnecessary code"
}
 
C

captainlionbug

Guest
What didn't work? The player doesn't get frozen? It throws an error? Where do you put your global variables?
 
S

Schoolboyz

Guest
It did work, but the animation doesn't play. It only gets stuck on the first sprite, and then stays like that (after the alarm is done, it doesn't go back to normal). I put the variables in the create event. I already stated everything in the previous reply if you are looking for my code.
 
S

Schoolboyz

Guest
When I used this code:
At the top of the event:

Code:
if (alarm[0] >= 0) // If alarm is going
    exit; // Cancel the rest of the event
The animation actually played but never went back to normal.
 
D

DaMuffin

Guest
It did work, but the animation doesn't play. It only gets stuck on the first sprite, and then stays like that (after the alarm is done, it doesn't go back to normal). I put the variables in the create event. I already stated everything in the previous reply if you are looking for my code.
I tried your method but unfortunately it didn't work :(
Variable in create event:
Code:
global.frozen = true;
Alarm code:
Code:
global.frozen = false;
Step event code:
Code:
if global.frozen = true
    sprite_index = Metal_Idle
    {
        image_speed = 10
        alarm[1] = 100
    }
   
if global.frozen = false
{
"long unnecessary code"
}
You aren't setting global.frozen back to false nor are you checking to make sure that the alarm isn't already set before resetting it. That is causing global.frozen to never be false in the first place. Also, and I may be wrong about this but, because you have "sprite_index = Metal_Idle" outside the brackets the sprite is being reset every step.

In your alarm event put:
Code:
global.frozen = !global.frozen; //This will make the variable the opposite of what it currently is.
alarm[1] = 100; //This will reset the alarm when it is done.
Hope this helps.
 
S

Schoolboyz

Guest
Ugh. Everyone is trying to help yet nothing is working and I don't see what's wrong.

Create event variable code:
Code:
global.frozen = true;
Alarm 1 event code:
Code:
global.frozen = !global.frozen;
Step event code:
Code:
if global.frozen = true
    {
        sprite_index = Metal_Idle
        {
               image_speed = 10
        {
        alarm[1] = 100
    }
else
{
....
}
If anyone knows what I'm doing wrong, please let me know. When I entered this code he just sits there. The sprite is correct but the sprite animation doesn't play and he never goes back to normal.
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
Okay, if global.frozen == false, the alarm will never run again, and if global.frozen == true, it will always be getting set as it'll get set to 100 every step... You should reset the alarm in the alarm event itself rather than in the step event:

Code:
// CREATE
global.frozen = true;
alarm[0] = 100;

// ALARM[0]
global.frozen = !global.frozen;
alarm[0] = 100;

// STEP EVENT
if global.frozen == true
{
if sprite_index == Metal_Idle
    {
    image_speed = 10;
    {
}
else
{
....
}
Also note that for comparisons use == and for assigning use =.

:)
 
S

Schoolboyz

Guest
Okay, if global.frozen == false, the alarm will never run again, and if global.frozen == true, it will always be getting set as it'll get set to 100 every step... You should reset the alarm in the alarm event itself rather than in the step event:

Code:
// CREATE
global.frozen = true;
alarm[0] = 100;

// ALARM[0]
global.frozen = !global.frozen;
alarm[0] = 100;

// STEP EVENT
if global.frozen == true
{
if sprite_index == Metal_Idle
    {
    image_speed = 10;
    {
}
else
{
....
}
Also note that for comparisons use == and for assigning use =.

:)
Thanks for the information ==, I actually had a problem with that earlier which i was able to fix :) As for the code, the alarm works (FINALLY!). When the room starts, he pauses for a bit, then continues as normal, but he doesn't change to Metal_Ilde and the alarm infinitely resets ( he pauses when the room starts, begins to move, and then after a bit he pauses again, rinse and repeat)
 
The last bit of code you posted only needs one edit - move the alarm set to the Create event. If you're not using global.frozen for any other purpose but this, don't make the variable global.
 
S

Sinaz20

Guest
Another solution-- something I typically use-- is to create child objects that represent different states. So first you make a relatively empty object as the core parent. You might use it to declare initial properties, default sprite, etc, and set an initial state.

Then you create child objects that only have the behavior coded to service that state. For instance, I might create an object for walking, an object for attack, an object for jumping... this way I can use less logical switching and just write discrete code for each state/behavior and the hooks to instance_change the object from state to state.

So your hypothetical child object "idleObject" (perhaps) here would have an empty step event, and an alarm event. Another child object representing whatever the default state would set the alarm when appropriate, then call instance_change(idleObject, false) to convert it to the the "idleObject." The alarm event of "idleObject" would have another instance_change() call to return it to the default state.

...make sense?
 
S

Schoolboyz

Guest
Honestly I have no idea which one of you it was, but it finally worked :D Thank you ALL so much for everything you've done for. Sorry if it was a little frustrating lol
 

Hyomoto

Member
So, everyone here was trying to help but I didn't see anyone really explain what you are trying to do or why any of this happens so I just wanted to add some amplifying discussion here. The step event is a type of event that happens every frame. So, if your game is set to run at 60 frames per second, it should be called 60 times every second. Unlike the draw events, there is no way to simply 'skip' the step events: if they contain code, they will be called. That said, the real question you are asking is how do I fulfill an arbitrary condition? In your case you want the game to wait a little while and then resume processing. The core of this is a simple if statement:
Code:
if something == true {
  // do this
} else if something == false {
  // do this
}
Now this is a bit verbose, but the principle is simply that we are giving ourselves two portions of our code. The first will only be called if something is true, the second is called only if the something is false. If you have made it this far, I'm guessing you have a handle on that, so let's combine our two ideas here. The timers work by counting down by 1 each frame. If there are 60 frames in a second, they will do this 60 times in one second (thus making 60 the length of a second). When they hit '0' they call the alarm event and are set to -1 to let the program know they no longer need to count down. Therefore you may be tempted to do something like this:
Code:
if timer[ 0 ] > -1 {
  exit;
} else {
  // do this
}
If you have your eagle eyes on you might have noticed this is a bit redundant. If we put all of our code into the else block, then the exit we perform isn't particularly useful here. As was suggested above, this is functionally identical to:
Code:
 if timer[ 0 ] > -1 { exit }
// do this
But here's the thing, there are actions we may still want to take while the counter is going down, and if we used this method we'd need to put them into both blocks of code. So, for simplicity, we could just instead is isolate code that should run when the timer ISN'T counting down, namely our movement code. Instead we create a very specific condition and place our code there, in this case we say "if the timer isn't running, then do this code". By eliminating the exit statement we allow the rest of the script to still run.
Code:
if timer[ 0 ] =! -1 {
  // do this
}
// always do this
And to return to my original paragraph, this is all just fulfilling an arbitrary condition, in this case we're just asking what should the player not be able to do while the timer is running? To put it simply, we are saying DO NOT DO THIS unless THIS IS TRUE. That is the core of structuring any type of logic and is the backbone of all coding. Hopefully that gives a little more supporting information. Have fun and keep coding!
 
Last edited:
S

Schoolboyz

Guest
So do timers and alarms have the same function or should I be using them in different situations? Like in this example, would it have been easier to simply use the timer since I was trying to delay the step event? Aside from that, thank you for the clarification - definitely something I must keep in mind from now on.
 

Hyomoto

Member
So do timers and alarms have the same function or should I be using them in different situations? Like in this example, would it have been easier to simply use the timer since I was trying to delay the step event? Aside from that, thank you for the clarification - definitely something I must keep in mind from now on.
So, I'm going to use a smidgen more complexity here, but it might help you understand the timers a little bit better. The first thing to keep in mind is NOTHING HAPPENS SIMULTANEOUSLY. NOTHING. Every instruction, and every event has to happen one at a time. The timers and alarms are just there to simplify things, but they exist outside of the step event and are called when they are called. If you made your own timer, it would look like this:
Code:
// create event
myTimer = 60;
Code:
// step event
if myTimer > 0 {
  myTimer = myTimer - 1;
  
  if myTimer == 0 {
    // alarm
    
    myTimer = -1;
  }
}
Timers are incredibly simple. All the built-in timers are doing is allowing you to avoid writing that block of code a bunch of times if you have a lot of timers you want to use. To digress ever so slightly, this is how timing in general works, simply asking the program to not do stuff until a criteria has been met. In the case of the timer, that criteria is that it is no longer running, which we know because it is equal to -1. So, to get back to your question specifically, it all depends. Let's extrapolate this a bit and ask: how would you make the game pause? You might say, 'okay, I have this timer, and as long as it isn't -1 the character can't move' so you might just choose to set the timer. Well, that would lead to a situation where you could only pause for a set amount of time. To fix this you might either choose a really, really high number expecting no one will pause the game for a thousand minutes, or you could just keep setting the timer. However, now we have a new issue, what about all the other things that need to be paused? Like enemies and animations? Do we have to set timers for all of them too? The answer is no, we could just have all of them share the same timer. Or, since it's pointless for pausing, we could just drop the timer altogether and make ourselves a global variable:
Code:
if global.pause == true { exit }
The reason I bring up this exact example is because where, and why, you use not just a timer, but a condition is definitely important. This quickly becomes a discussion about scope, but to simplify: a program is literally a series of smaller and smaller ideas. A 'game' is made up of 'levels', and those 'levels' are made up of 'characters' and 'obstacles' and 'characters' are made up of the 'player' and 'enemies'. So when we decide to implement something like a pause, the question is, at what level (or scope) is this appropriate? Should the entire game be paused when we press start? Or perhaps just the level? Or even maybe just the characters? This will determine both where we define that 'pause', and what objects need it as a condition.

That's a bit of a large, wide answer so I'll leave it at that for now. If you have more questions, feel free to ask them.
 
Top