Jump to content
  • Advertisement
  • 01/06/16 07:13 AM
    Sign in to follow this  

    Brain Dead Simple Game States

    General and Gameplay Programming

    Klutzershy

    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!



      Report Article
    Sign in to follow this  


    User Feedback


    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.

    Share this comment


    Link to comment
    Share on other sites

    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

    Share this comment


    Link to comment
    Share on other sites

    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".

    Share this comment


    Link to comment
    Share on other sites

    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.

    Share this comment


    Link to comment
    Share on other sites

    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...

    Share this comment


    Link to comment
    Share on other sites

    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.

    Share this comment


    Link to comment
    Share on other sites

    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

    Share this comment


    Link to comment
    Share on other sites

    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.

    Share this comment


    Link to comment
    Share on other sites

    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.

    Share this comment


    Link to comment
    Share on other sites

    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.

    Share this comment


    Link to comment
    Share on other sites

    @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.

    Share this comment


    Link to comment
    Share on other sites

    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?

    Share this comment


    Link to comment
    Share on other sites

    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 ?

    Share this comment


    Link to comment
    Share on other sites

    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?

    Share this comment


    Link to comment
    Share on other sites

    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.)

    Share this comment


    Link to comment
    Share on other sites


    Create an account or sign in to comment

    You need to be a member in order to leave a comment

    Create an account

    Sign up for a new account in our community. It's easy!

    Register a new account

    Sign in

    Already have an account? Sign in here.

    Sign In Now

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!