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();
}