• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Is it okay to do a state system this way?

K

Kamon145

Guest
Hello everyone, I've been using a state system with a switch statement in my step event to keep things organized and only running what needs to run, Ive been doing it by setting up a variable in the "create" event thats something like
state = "idle"
with quotations indicating i am assigning a word, and in my step event:
switch(state)
{
case "idle":
{
idle_script;
}break;
ect ect.. This system has been working for me but Ive been looking at how other people do it and most seem to include setting up enums or something similar. I have not found many examples of people doing it the way I have been doing it so that leads me to wonder, is there anything wrong with doing it the way Ive been doing it, with variables assigned to words? Will this cause me problems on bigger projects or is it just considered bad practice?
Any input is appreciated, like I said I haven't really encountered any problems with this system.. yet.. But I would like to know ahead of time if there is a problem! Thanks!!
 
A

Annoyed Grunt

Guest
It's better to use enums for the simple reason that doing so lets you take advantage of the syntax checking system. There are so many ways you can misspell a string, and if you do you'll see your switch jump to its default behavior for no apparent reason. You'll have to go in your code and find exactly where you typed it wrong. If you use an enum, instead, a nice syntax error will plop up when you try to compile telling you exactly where the issue is. It's simply more robust and, additionally, also cleaner and more aesthetically pleasing.
 
K

Kamon145

Guest
Ahh thank you, I will do some more research on enums and start switching to that method :)
edit* One last thing though, are enums like global variables? Like if i had multiple player objects, all essentially coded the same, would I run into problems using the same enums for all players?
 
N

NeZvers

Guest
I'd suggest a better approach.
1. Have your states in scripts (ex: sm_idle)
2. Create enums for each state and give script name as value
Code:
enum sm{
    idle = sm_idle,
    run = sm_run
}
3. Have variable that store current state:
Code:
state = sm.idle;
4. And call your state in step event with one line:
Code:
script_execute(state);
5. have conditions in state scripts for switching out to different state.

That's all it takes to have a state machine.
 
A

Annoyed Grunt

Guest
Ahh thank you, I will do some more research on enums and start switching to that method :)
edit* One last thing though, are enums like global variables? Like if i had multiple player objects, all essentially coded the same, would I run into problems using the same enums for all players?
Yes, an enum is a global variable. There is functionally no difference between:

Code:
global.state_idle = 0;
global.state_running = 1;
global.state_jumping = 2;
global.state_climbing = 3;
...
And

Code:
enum State {
     idle,
     running,
     jumping,
     climbing
}
I'd suggest a better approach.
1. Have your states in scripts (ex: sm_idle)
2. Create enums for each state and give script name as value
Code:
enum sm{
    idle = sm_idle,
    run = sm_run
}
3. Have variable that store current state:
Code:
state = sm.idle;
4. And call your state in step event with one line:
Code:
script_execute(state);
5. have conditions in state scripts for switching out to different state.

That's all it takes to have a state machine.
This is an ok method, but it falls short if you want to have objects with different behavior because you are essentially hardcoding the scripts. A more flexible way would be to add a sizeof entry to your enum:

Code:
enum State {
     idle,
     running,
     jumping,
     ...
     sizeof
}
Unless specified otherwise, enum entries are specified in order (the first one is 0, the second one is 1, etc), so adding a sizeof entry gives you the effective size of the enum. This lets us instantiate an array of the size of the enum. You can then by hand specify what script should be executed for each state.

Code:
///@description Create Event of a Player
state = State.idle;
all_states = array_create(State.sizeof, noone);
all_states[@ State.idle] = script_idle;
all_states[@ State.running] = script_running;
...
This is especially useful because it handles unused states automatically.

Code:
///@description Step event (or wherever you execute the state machine) of Player
var state_script = all_states[state];
if state_script != noone {
     script_execute(state_script);
}
And you can also have default behavior if you replace noone with a default script.

Code:
all_states = array_create(State.sizeof, script_default);
 
N

NeZvers

Guest
Well, that was an example. For myself I have different enums for different objects (ex: sm_camera.follow,sm_player.run).
 

NightFrost

Member
Yeah enums are a much better choice as it is less error prone than strings due to autocomplete. As for state scripts, I generally do not create scripts for operations that need to be run in only once place ever, but may split its components into smaller parts if they are needed in multiple places. For example in a platformer, code fragments that are required by player and enemy instances both. So my state operation would look like:
Code:
// IN PLAYER STEP EVENT

// Idle state.
if(State == Player_State.Idle){
    // Check if standing on moving terrain tile.
    var On_Ground = scr_check_ground();
    var Move = scr_get_move();
    var Drop = scr_get_drop();
    var Jump = scr_get_jump();
    if(Move || Jump){
        scr_check_collision();
    }
    if(Move) State = Player_State.Move;
    if(Jump || Drop || !On_Ground) State = Player_State.Jump;
}
Getting those true/false return to the vars wouldn't be strictly necessary as I could do the tests inside other scripts too. I write it this way because it gives me a bit better overall view of how the states switch and what they do.
 

Sabnock

Member
if you declare your enums in a script called say ENUMS they are setup automatically when the program compiles
 

NightFrost

Member
You can decalre the enums anywhere, basically. What the compiler does is, it sniffs out all the enum declarations (during a pass where it checks for code validity I suppose) then replaces all the references to enums with their actual values. The declarations themselves are dropped out as they're no longer needed. I used to declare all enums in init object but these days I do that in objects that use them as it feels a more proper context and makes it faster to find the exact declaration I want to change.
 
Top