Switch Getting Ignored

P

potatato

Guest
I've simplified it, but it's basically what I am trying to do.
When a user presses a key it changes the state to idle and command to stop.

Step Event
GML:
switch(state) {
    case "idle":
        if (command == "go") {
            // do stuff
        } else if (command == "stop") {
            if(alarm[0] < 0) {
                alarm[0] = room_speed * 5
            }
        }
   
    break;

    case "move":
        //do moves
    break;

}
Alarm[0]
GML:
state = "move"

command = "go";

What actually occurs (found by debug message):
Alarm[0] counts down from 300 (60*5). The alarm does go off and the state and command are set correctly back to move and go respectively.

BUT then in the step event it goes to case "idle" and goes to "stop" again, which goes into an infinite loop. How do I make my step event respect my alarm frame?
 
Last edited by a moderator:

samspade

Member
You're missing a colon after move, which I don't know if that would cause the issue, but more importantly there is some important code not posted here. Specifically, what sets state back to "idle"? (The code that is posted would switch the state to "move" where it would stay forever.)
 
P

potatato

Guest
You're missing a colon after move, which I don't know if that would cause the issue, but more importantly there is some important code not posted here. Specifically, what sets state back to "idle"? (The code that is posted would switch the state to "move" where it would stay forever.)
In my actual code, there's a colon after move. I'll make the change in the original post.

There's logic in the //do moves that makes the switch back to "idle" once it reaches a target x and target y. The problem is elsewhere of that though :/
 
The problem is not in the code you posted. By trying to simplify it, you've removed whatever is causing the error. Also, if you're not sure what's causing the error, telling other people "that's not causing the error" is counter-productive, as you don't know what's causing it.
 

samspade

Member
Agreed with @RefresherTowel, the code you posted is not the cause of the error, at least not entirely, and would require other code to cause the problem you're describing. That might be in the //do moves portion, or it might be somewhere else entirely. I would post the //do moves section so people could look at it, but it might also be worth doing a search through your code for any state = "idle" since it is getting switched back at some point.

If you have removed any other code from the switch statement, especially other cases, I would post that too.
 
P

potatato

Guest
The problem is not in the code you posted. By trying to simplify it, you've removed whatever is causing the error. Also, if you're not sure what's causing the error, telling other people "that's not causing the error" is counter-productive, as you don't know what's causing it.
That's fair. It's ugly cause it's super long haha.

I do know what doesn't cause it for some part though. I've also double checked by placing a 💩💩💩💩-ton of show_debug_message before and saw that in no case did it go into move for the case. It's bad if I didn't do any research and asked for help haha.

GML:
if (!abandoned) {
    switch(state){
        case "idle":
            switch(command) {
                case "go":
                    if (alarm[0] < 0) {
                        delay = choose(30);
                        alarm[0] = delay;
                    }
                break;
                case "stop":
                    if (alarm[0] < 0) {
                        alarm[0] = room_speed * 5; //babies stop for 2 seconds
                    }
                break;
            }
    
            break;
        case "move":
            //listen to command first
            if (command != "go") {
                state = "idle"
            
            } else {
                //follow parent direction
                _dir = point_direction(x,y, parent.x, parent.y)
                dir = floor(_dir/90)
    
    
    
                // TODO: work out speed farther away
                dist = distance_to_object(parent);
                if (dist > 200) {
                    move_speed = 3
                }
            
            
                //move to parents direction
                // parent above
                if (y > parent.y + parent_distance) {
                    y -= move_speed
                } else if (y < parent.y - parent_distance) {
                    y += move_speed
                }
                if (x > parent.x + parent_distance) {
                    x -= move_speed
                } else if (x < parent.x - parent_distance) {
                    x += move_speed
                }
    
                //change to idle if near parent's butt
                if (parent.dir == 0){
                    if(x > parent.x - parent_distance && (parent_distance >= abs(parent.y-y))) {
                        state = "idle"
                    }
                } else if (parent.dir == 1) {
                    if(y > parent.y - parent_distance && (parent_distance >= abs(parent.x-x))) {
                        state = "idle"
                    }
                } else if (parent.dir == 2) {
                    if(x < parent.x + parent_distance && (parent_distance >= abs(parent.y-y))) {
                        state = "idle"
                    }
                } else if (parent.dir == 3) {
                    if(y < parent.y - parent_distance && (parent_distance >= abs(parent.x-x))) {
                        state = "idle"
                    }
                }
    
            }
    
            break;
    }
}
sprite_index = asset_get_index("spr_"+baby_type+"_" + state + string(dir));
The command is set by the parent. Also this doesn't occur when the parent_distance hits any of the conditionals that make the state="idle" in terms of distance.


if (instance_exists(obj_babyHealthy)) {
obj_babyHealthy.command = "stop"
}
 
Last edited by a moderator:
P

potatato

Guest
Also instead of straight answers, the hard part is I want to understand the concept so I can solve an issue if something else happens. ;_;
 

samspade

Member
I would put a break point or debug message on/before every line that has state = "idle" and every line that has command = "stop" (or really any line that would change the command from go). My guess is that one of these statements is true when you don't actually want it to be. For example, perhaps one of the collisions is wrong or (most likely) perhaps command is being changed.

Also what is meant by parent in this case? Parents in the inheritance since do not exist/are not present in the game. Do you mean that you have instance a which creates instance b and that instance a keeps track of its instance bs and instance b keeps track of its instance a?

One final note is that your if (instance_exists) line seems suspect. Not only does it do one of the things that would mess up the state (changing command to stop) it uses an object id instead of an instance id which is only appropriate if there is one, and only one, instance of an object present. It also is without context so I can't tell if there is a check or not because if there wasn't and that code was running it would always be setting the command variable to stop (e.g. not go) and thus never running the move state.
 
P

potatato

Guest
I've checked these cases
  1. In move: at the other conditionals - I haven't placed the objects in a place to go in the if statements. Checked by seeing if there is a debug message
  2. In the other command=stop, there's only the one at the parent (the mom/dad not object mom/dad) and it definitely changes the babyHealthy's command
I haven't checked:
  1. In move: at the !go
    1. Checking now.
    2. I press shift to have the "parent" send command "stop".
    3. It does go to stop and it does fire the alarm, but now it's cycling the following manner:
      1. STOP --> alarm 300 --> State set at move...but go is not set as the command now. It's still at stop?
      2. BUT the alarm is going off every 300 seconds again, which it shouldn't since the move and command are set?
Follow up questions:
  • Can you only set one variable per alarm? Is that why it's not working?
---------------------
The parent is my bad naming convention cause I need to find a synonym for an animal parent :/ It's an object that's a mom/dad animal. Probably makes things a bit confusing haha. I haven't decided on the gender of the "parent" or the creature name :RIP:

---------------------
I checked the documentation, for instance_exists and in the example, the use case is to pass an object id: https://docs2.yoyogames.com/source/...ances/instance_functions/instance_exists.html

---------------------
(PS also thanks for the criticism y'all for not providing the full code. I'll do that moving forward.)
 

samspade

Member
Can you only set one variable per alarm? Is that why it's not working?
I'm not sure what this means. Any given alarm (e.g. alarm[0] or alarm[3]) can hold only one value. That value automatically counts down and when it hits zero, goes off and fires the corresponding alarm event. All of the code in the alarm event runs.

I checked the documentation, for instance_exists and in the example, the use case is to pass an object id
That part is true, the part that I was commenting on is how referencing an instance works when using an object id. Objects do not exist when you are running your game, instances of those objects exist. So using an object id to reference an instance only works if there is one, and only one, instance of that object present. Otherwise, the object id essentially picks an existing instance at random (or all instances on some platforms I believe) and sets the value in those instances.

My guess is in reading your comments that what is happening is that your parent is firing the command stop line more often than you want it to, perhaps even every frame. So that when the alarm fires and sets command to go it is immediately reset.
 
P

potatato

Guest
I think I fixed it. I just needed to remove the
GML:
   if (command != "go") {
                state = "idle"
            
            }
More reason for in the future to add all the code in the first place haha, which is a good valuable lesson :D

---------
(or all instances on some platforms I believe)
In GML, it looks like it's choosing all instances if I read the documentation right, which is what I want.

Unfortunately, I don't completely understand what the logic is for the reason why the fix above works. Maybe it is because of the latter reason with the instance_exists, but that piece is within each individual code (shouldn't each one have the command only locally and not impacted by the parent?).
 
P

potatato

Guest
Or not...for some reason the alarm is still firing in the background.
 
P

potatato

Guest
Final edit:

Don't know how to close thread. I don't understand the concepts ;_; but it is fixed. Thank you again.
 
Top