Currently all my games use a very simplistic game state "engine" that is just auses switch statementstatements everywhere. It's very messy, violates DRY horribly, and does not scale very well.
enum STATE {
LOADING,
TITLE,
LEVEL_ONE,
LEVEL_TWO,
LEVEL_THREE,
LEVEL_FOUR,
LEVEL_FIVE,
LEVEL_SIX,
// LEVEL_SEVEN,...
WIN,
GAME_OVER,
CREDITS,
}GAME_STATE;
void Input() {
keyboard->Update();
//Check if the user wants to quit, if so, jump out.
if(keyboard->KeyDown(KEY_ESC)) quit = true;
if(quit) return;..
switch(GAME_STATE) {
case LOADING:
break;
case TITLE:
if(keyboard->isKeyPressed())
NEXT_LEVEL = true;
break;
case LEVEL_ONE:
case LEVEL_TWO:
case LEVEL_THREE:
case LEVEL_FOUR:
case LEVEL_FIVE:
case LEVEL_SIX:
case LEVEL_SEVEN:
if(keyboard->KeyPress(KEY_PAUSE))// return;...
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) {
//Do nothing if user wants to quit.
if(quit) return;
if(keyboard->KeyPress(KEY_PAUSE)) return;
deathTimer = dead;
if(NEXT_LEVEL) {
createFood();
LoadLevel();
// }...
switch(GAME_STATE) {
case LOADING:
break;
case TITLE:
break;
case LEVEL_ONE:
case LEVEL_TWO:
case LEVEL_THREE:
case LEVEL_FOUR:
case LEVEL_FIVE:
case LEVEL_SIX:
case// LEVEL_SEVEN:...
ProcessLevel();
if(GAME_STATE == LEVEL_SEVEN) {
showWalls = true;
sh->Index(BLEVELSEVEN)->SetAlpha(0);
clear_bitmap(FOG_OF_WAR->GetImage());
rectfill(FOG_OF_WAR->GetImage(), 0, 0, 226, _gw->GetHeight(), TRANSPARENT);
rectfill(FOG_OF_WAR->GetImage(), 798, 0, _gw->GetWidth(), _gw->GetHeight(), TRANSPARENT);
for(int i = 0; i < MAX_PLAYERS; i++) {
circlefill(FOG_OF_WAR->GetImage(), player[i]->GetX() + player[i]->GetSprite()->GetCenterX(), player[i]->GetY() + player[i]->GetSprite()->GetCenterY(), 90, TRANSPARENT);
// }...
}
break;
case WIN:
break;
case GAME_OVER:
break;
case CREDITS:
break;
}
}
void Render() {
//Do nothing if the user wants to quit.
if(quit) return;
//Start render process.
_gw->StartRender();.
switch(GAME_STATE) {
case LOADING:
break;
case TITLE:
sh->Draw(_gw->GetBackBuffer(), sh->Index(0));
break;
case LEVEL_ONE:
case LEVEL_TWO:
case LEVEL_THREE:
case LEVEL_FOUR:
case LEVEL_FIVE:
case LEVEL_SIX:
case LEVEL_SEVEN:
//BACKGROUND
RenderLevel();
//OBJECTS
//PILLS
for(int i = 0; i < MAX_PILLS; i++) {
if(pills[i]->IsAlive()) sh->Draw(_gw->GetBackBuffer(), pills[i]->GetSprite());
}
//FOOD
for(int i = 0; i < MAX_FOOD; i ++) {
if(food[i]->IsAlive()) sh->Draw(_gw->GetBackBuffer(), food[i]->GetSprite());
if(hasFood[i] == true) sh->Draw(_gw->GetBackBuffer(), dynamic_cast<AnimatedSprite*>(food[i]->GetSprite())->GetFrames()[i], 800, 100 + (i * 32), WHITE, 0, 255);
}
if(showWalls) {
//WALLS
for(int i = 0; i < MAX_WALLS; i++) {
rectfill(_gw->GetBackBuffer(), walls[i]->GetX(), walls[i]->GetY(), walls[i]->GetX() + walls[i]->GetWidth(), walls[i]->GetY() + walls[i]->GetHeight(), walls[i]->GetColor());
}
for(int i = 0; i < MAX_HIDDEN; i++) {
rectfill(_gw->GetBackBuffer(), hidden[i]->GetX(), hidden[i]->GetY(), hidden[i]->GetX() + hidden[i]->GetWidth(), hidden[i]->GetY() + hidden[i]->GetHeight(), hidden[i]->GetColor());
}
}
if(showWaypoints) {
for(int i = 0; i < MAX_WAYPOINTS; i ++) {
rectfill(_gw->GetBackBuffer(), waypoints[i]->GetX(), waypoints[i]->GetY(), waypoints[i]->GetX() + 7,waypoints[i]->GetY() + 7, BLACK);
}
}
//Copy area for teleports
copyTeleports();
for(int i = 0; i < MAX_PLAYERS; i++) {
if(player[i]->IsAlive()) {
switch(player[i]->GetFacing()) {
case Actor::RIGHT:
sh->Draw(_gw->GetBackBuffer(), player[i]->GetSprite());
break;
case Actor::LEFT:
sh->Draw(_gw->GetBackBuffer(), player[i]->GetSprite());
break;
case Actor::UP:
sh->Draw(_gw->GetBackBuffer(), player[i]->GetSprite());
break;
case Actor::DOWN:
sh->Draw(_gw->GetBackBuffer(), player[i]->GetSprite());
break;
}
} else {
sh->Draw(_gw->GetBackBuffer(), player[i]->GetSprite());
}
}
//ENEMIES
for(int i = 0; i < MAX_ENEMIES; i++) {
if(enemies[i]->IsAlive()) {
switch(enemies[i]->GetFacing()) {
case Actor::RIGHT:
sh->Draw(_gw->GetBackBuffer(), enemies[i]->GetSprite());
break;
case Actor::LEFT:
sh->DrawFlip(_gw->GetBackBuffer(), enemies[i]->GetSprite(), SpriteHandler::VERTICAL);
break;
case Actor::UP:
enemies[i]->GetSprite()->SetRotation(-90.0f);
sh->DrawRotate(_gw->GetBackBuffer(), enemies[i]->GetSprite());
break;
case Actor::DOWN:
enemies[i]->GetSprite()->SetRotation(90.0f);
sh->DrawRotateFlip(_gw->GetBackBuffer(), enemies[i]->GetSprite(), SpriteHandler::HORIZONTAL);
break;
}
}
}
for(int i = 0; i < MAX_PUPS; i ++) {
if(powerups[i]->IsAlive()) sh->Draw(_gw->GetBackBuffer(), powerups[i]->GetSprite());
}
//MOVED FOOD TO BEFORE TELEPORT COPY SO FOOD DOESN'T GET COVERED.
for(int i = 0; i < MAX_PLAYERS; i++) {
drawUI(i);
}
//Draw area for teleports.
drawTeleports();
//Draw fog of war for level seven.
if(GAME_STATE == LEVEL_SEVEN) {
sh->Draw(_gw->GetBackBuffer(), FOG_OF_WAR);
}
//Show level number
textprintf_ex(_gw->GetBackBuffer(), UI_font->GetFont(), 20, 0, WHITE, -1, "LEVEL %d", GAME_STATE - 1);
//Show PAUSE.
if(keyboard->KeyPress(KEY_PAUSE)) {
textout_ex(_gw->GetBackBuffer(), UI_font->GetFont(), "PAUSED", (_gw->GetWidth() / 2) - (UI_font->GetLength("PAUSED") / 2), (_gw->GetHeight() / 2) - (UI_font->GetHeight() / 2), WHITE, -1);
}..
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();
}