Best practice for state-based game design?

Dsharp

Member
Working on a strategy game. Right now, what I've got is only nominally state-based. There's an "initializing state" that lasts a few frames at most upon startup, and then you're thrown right into a gameplay demo (just able to move units around really).

Obviously I'm gonna want menus to select options from in combat, dialogue scenes out of combat, a main menu, etc.

But what's the best practice for controlling these states, seeing as I've got multiple objects? For example, I've got a keyboard object that detects input from keys, but a cursor object that reads mouse movement and handles click events based on context (EX: selecting/deselecting units).

Of course, in a menu I don't want to mess with moving units - the mouse should only interact with the menu options. Same for the keyboard. So do I just wrap up the entire cursor/keyboard object step events in case statements to check what state the game is in? Do I do that for every object type that would need to know what state we're in (IE, don't draw units on the battlefield if there current state is a full screen menu, don't scroll the camera in that menu, etc)

Or should I rework the way my code is organized, packing everything into one "master" game object, that is in complete control of the state? The master object would handle most of the tasks I'm delegating between objects all in its own step event. Maybe by taking the step events of other objects and dividing them into scripts?

Or is there some other solution? Is there any consensus at all? I'm sure there are some guides out there, but no tutorials I've found really get into the organization of larger-scale games. So pointing me in the right direction is all I really need.
 

Dsharp

Member
Adding on to this, should I be making separate objects for different rooms? As in, a cursor for a battle map, and a cursor for the menus? Then I just call obj_cursor_menu for the main menu, and obj_cursor_battle for battle maps, etc?

Apologies for second post, this was originally an edit but somehow I accidentally posted a comment instead? Dunno what happened there.
 

TheouAegis

Member
If you are using GMS2.3+ (the current beta), you could tell all the objects what to do using local methods, then have a controller tell them what methods to use when needed.

I personally use a master object with scripts or user events inside everything else.
 

Dsharp

Member
If you are using GMS2.3+ (the current beta), you could tell all the objects what to do using local methods, then have a controller tell them what methods to use when needed.

I personally use a master object with scripts or user events inside everything else.
What do you mean by local methods, exactly? I know you can call functions in the beta, meaning you can treat scripts as more of an organizational tool to contain functions, rather than calling scripts like functions themselves. Dunno about local methods though.

Haven't been using any user events either, but I've found some info on those so I'll take a look. Thank you!
 

Dsharp

Member
You don't have to use scripts anymore in 2.3. you can define functions inside each object and that function can be unique to that object
Huh, I don't think I saw that in the page I read. That's neat, though. I don't have 2.3 right now, but I'll look into updating to it. It sounds like it might break a lot of my code, but I'm early enough into development that I'm willing to take the time to fix that now, assuming 2.3 is stable and doesn't have some sort of downside I don't know about.

So, if I'm understanding user events correctly, they can be used sort of like a state machine. Or used to complement one. For example, I can have my master object say:

If (gameState = "mainMenu")
With(All)
event_user(0);

Where event_user(0) is the behavior I want my mouse, keyboard, etc objects to use for those states. Is that a valid way to use user events?
 

Yal

šŸ§ *penguin noises*
GMC Elder
Nothing stops you from having recursive state machines: e.g. main state is "take input", "execute player's actions", "enemy AI", "execute enemy actions" etc, while you have a sub-state-machine for all of those other states: enemy AI would first find the optimal action order, then go through all enemies one by one and pick an action, the player's state machine moves forth and back between states depending on which menu is currently active, and so on.

Each substate machine should have a defined "start here" substate that sets all the FSM variables up, and transition from one upper-state to another should always reset substate to that state so there's no potential for "leaks" between substate machines.
 

Dsharp

Member
That's an interesting idea too, I hadn't considered that.

Gah, there are so many possibilities here, but it kinda sounds like for the most part it's up to personal preference. I'll have to do a lot more research to figure out how I want to organize this prototype into a more-complete game, but thanks for the ideas!
 
Top