Brain Dead Simple Game States

Published January 06, 2016 by Boreal, posted by Klutzershy
Do you see issues with this article? Let us know.
Advertisement

Lately, I've realized that game state management is always vastly overcomplicated. Here's a brain dead simple system that does everything you probably need in a straightforward way.

Just what the heck is a game state?

Well, what happens when you boot up a game? You probably see some credit to the engine, get shown "the way it's meant to be played", and maybe watch a sweet FMV cutscene. Then you get launched into the menu, where you can tighten up the graphics on level 3 and switch the controls to accommodate your DVORAK keyboard. Then you pick your favourite level, and start playing. A half an hour later, you've had too much Mountain Dew, so you have to pause the game for a few minutes to stop the action to be resumed later. That's about 4 game states right there: introduction, menu, gameplay, pause screen.

Alright, how do we start coding?

The job of a state is pretty simple. Generally, it needs to update something, and then draw something. Sounds like an interface to me. public interface State { public void update(float dt); public void draw(); } You'd then have concrete states like Menu or Play that implement this interface. Now, I'm going to put a little spin on it, by changing the type of the update method. public interface State { public State update(float dt); public void draw(); } Why did I do that? Well, one of the important parts about game states is the ability to change between them. A game wouldn't be very fun if all you could do was watch the intro FMV over and over again. So the update method now returns whichever state should be used next. If there's no change, it should just return itself. public class Menu implements State { public State update(float dt) { if(newGameButton.clicked()) { return new Play("Level 1"); } return this; } public void draw() { drawSomeButtons(); } } Now, the state management code becomes extremely simple, and doesn't require any separate manager class or anything. Just stick it in your main method or whatever holds the game loop. State current = new Intro(); while(isRunning) { handleInput(); current = current.update(calculateDeltaTime()); current.draw(); presentAndClear(); }

Wait, that's it?

Yup.

For real?

Nah, just kidding. Here's something really cool about this method. Take the pause state. You have to be able to unpause and return to what you were doing, unchanged, right? Usually, a stack is advocated. You push the pause state on to the stack, and pop it off when you're done to get back to the play state. You would then only update and draw the topmost state. I say, screw the stack. Have the pause state take a State in its constructor, which is stored, and then returned instead of the pause state itself when the update method detects that the game should be unpaused. If the pause screen needs to be an overlay over whatever was going on before the game was paused, that's really easy, too! public class Pause implements State { private State previous; public Pause(State previous) { this.previous = previous; } public State update(float dt) { if(resumeButton.clicked()) { return previous; } return this; } public State draw() { previous.draw(); applyFancyBlurEffect(); drawThePauseMenu(); } }

Closing Remarks

Although it may seem like this method requires garbage collection, it really doesn't. You might have to slightly complicate the barely logical "management logic" to accomodate languages without automatic destruction, but in general, the idea of handling transitions by returning different states will work just fine. I'm sure there are many more ways to use/abuse this system that I can't think of right now, and I appreciate all feedback! Thanks for reading, and I hope it helped!

Cancel Save
0 Likes 16 Comments

Comments

Klutzershy

There we go.

December 21, 2015 04:35 AM
Istarnion
Great! Really good for small games and simplifies exactly what beginners struggle with, namely where to create the statr objects, and how to transition between them. I will definitly be using this next time I do a game jam or something like that. Even as the starting point in a bigger game and add complications as you go.
January 04, 2016 08:53 PM
Gaiiden

I have no idea why this is scheduled to be published on Jan 05 2016 01:45 AM, in case anyone was wondering why it was approved but not yet on the main page

January 05, 2016 03:07 AM
Klutzershy

I was trying to edit it to fix the broken headers and I must have messed the time up. Though the last time I edited it, I made sure to set the time to "now".

January 05, 2016 04:19 AM
Khatharr

Just a note:


  current = current.update(calculateDeltaTime());
  current.draw();

drawing a state prior to its first update may cause flickers or etc depending on how you're set up. You may want to advocate update(0) in the state constructor or some other fix, or explain transitions.

Minor issue, though, since the article is focused on giving a simple explanation.

January 05, 2016 11:07 AM
Gaiiden

I was trying to edit it to fix the broken headers and I must have messed the time up. Though the last time I edited it, I made sure to set the time to "now".

for some reason an articles entire content is now forced between <p></p> tags, which can mess up the headers. I have no idea why for that either :P but at least good to know it's not resetting dates on its own too...

January 05, 2016 03:46 PM
Klutzershy

Argh, I hate this time system. It seems to default to UTC, while I'm at UTC-4 (Atlantic Time), so if I don't explicitly change the time to "Now" it sets it to publish 4 hours in the future.

January 05, 2016 06:59 PM
Gaiiden

yea that's an old one - I forgot about it since I've not messed with publication dates for a long while as the system just updates to the proper time when I approve them. Why are you touching it though? If you're making edits you should just make the edits and hit the Update Article button. No reason to mess with the date/time

January 06, 2016 03:28 PM
Klutzershy

Even if I'm editing the article, it defaults to "4 hours from now". I need to mess with it to get it to not revert back to a draft temporarily.

January 06, 2016 07:20 PM
Draika the Dragon

In java I have these "States" extend from JPanel, which opens up opportunities to use more of the inbuilt java utilities such as JButton for GUI use.

January 13, 2016 10:06 PM
cdoty

I would also add enter and exit functions to allow the states to initialize data before use and to clean up after they are done.

February 06, 2016 04:36 AM
Klutzershy

@cdoty:

Initialization may be done in the constructor and clean up in the destructor. It's not a finite state machine - the states are created ad hoc just before use instead of kept around and simply switched to. Of course, in a managed language like the article assumes, you would likely want to use a clean up method, because you have no idea when a destructor will be called by the GC.

March 12, 2016 08:03 PM
HuToday

Well, I appreciate your work. However, for a beginner like me who use unity, the transitions between "game states" are realized by switching between different scenes. Maybe I will use your system when I program a game without using the game engines...

BTW, what the ... is the comment above me? Ads?

April 28, 2016 05:45 AM
Europia79

This is fucking awesome.

Can you elaborate on newGameButton.clicked() and resumedButton.clicked() ?

They don't appear to be static and they're also not passed via the constructor ?

Shouldn't you get the user-input ? Then pass it along to the update() method ?

April 30, 2016 08:12 PM
Gregory Cheyney

Input handling should expressly be handled each game loop *before* processing the state -- as I understand it. Handling input within a state instance would be, what, WRONG?

August 24, 2016 03:16 PM
leeor_net

Input handling should expressly be handled each game loop *before* processing the state -- as I understand it. Handling input within a state instance would be, what, WRONG?

I disagree. I suppose it depends on how you set up your particular game but in the projects that I work in I have a similar system in place and each individual 'state' responds to input on its own. There is an EventHandler that processes events from the system and translates them into a list of events to which the states respond (e.g., mouse/keyboard input, window events, system events, etc.)

May 18, 2017 06:19 PM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!

Lately, I've realized that game state management is always vastly overcomplicated. Here's a brain dead simple system that does everything you probably need in a straightforward way.

Advertisement
Advertisement