Skip to main content
2 of 2
tag, make code example a bit shorter
congusbongus
  • 14.9k
  • 59
  • 91

Implementing game state without switch statements everywhere?

Executive summary

Are there any good tutorials on Game State FSMs, particularly OOP/OOD-based and not switch-statement-based?

Summary

Is there a practical process for creating a game state engine other than using a switch statement, preferably with examples? Wikipedia's event-driven FSM article only shows a switch statement and the article on FSMs is strictly theory-based with no practical examples.

Background

Currently all my games use a very simplistic game state "engine" that uses switch statements everywhere. It's very messy, violates DRY horribly, and does not scale very well.

Each state is treated as a level and must be checked at all three points throughout the game loop, i.e. Input, Processing, and Render. If a level or screen is added it must be added to all the switch statements.

Practical example of recreation of pac-man for educational purposes (seriously, this was a school project a few years ago):

enum STATE {
    LOADING,
    TITLE,
    LEVEL_ONE,
    LEVEL_TWO,
    // ...
    WIN,
    GAME_OVER,
    CREDITS,
}GAME_STATE;


void Input() {
    // ...

    switch(GAME_STATE) {
        case LOADING:
            break;
        case TITLE:
            break;
        case LEVEL_ONE:
        case LEVEL_TWO:
        // ...
            InputCommon();
            break;
        case WIN:
        case GAME_OVER:
            if(keyboard->KeyDown(KEY_ENTER))
                GAME_STATE = CREDITS;
            break;
        case CREDITS:
            if(keyboard->isKeyPressed())
                quit = true;
            break;
    }
}

void Processing(int dead) {

    // ...

    switch(GAME_STATE) {
        case LOADING:
            break;
        case TITLE:
            break;
        case LEVEL_ONE:
        case LEVEL_TWO:
        // ...
            ProcessLevel();
            if(GAME_STATE == LEVEL_SEVEN) {
                // ...
            }
            break;
        case WIN:
            break;
        case GAME_OVER:
            break;
        case CREDITS:
            break;
    }
}

void Render() {
    // ...

    switch(GAME_STATE) {
        case LOADING:
            break;
        case TITLE:
            sh->Draw(_gw->GetBackBuffer(), sh->Index(0));
            break;
        case LEVEL_ONE:
        case LEVEL_TWO:
        // ...

            // ...
            break;
        case WIN:
            sh->Draw(_gw->GetBackBuffer(), sh->Index(3));
            break;
        case GAME_OVER:
            sh->Draw(_gw->GetBackBuffer(), sh->Index(1));
            break;
        case CREDITS:
            sh->Draw(_gw->GetBackBuffer(), sh->Index(2));
            break;
    }

    //End render process, display to screen.
    _gw->EndRender();

}
Casey
  • 2.1k
  • 2
  • 18
  • 27