An efficiant game loop

Started by
38 comments, last by Genjix 19 years, 2 months ago
That is also a great method. Besides, I respect anyone who can implement inheritence in a game successfully.
-----------------------------Play Stompy's Revenge! Now!
Advertisement
I have a question regarding the noob method of a game loop. Is using a switch statement slow? Or does it just get cluttered...
--m_nPostCount++
Here is a tutorial about managing game states in C++, is very good and easy to follow.

http://tonyandpaige.com/tutorials/game1.html

Regards,
Oscar
Actually, there are indeed commercial, AAA games which implement the standard "noob" state-based loop... Even for a really complicated game, I'd be surprised if you need more than a handful of states.

Also, instead of using a switch statement, what you could in fact do is just have 1 game loop.... but then, the current game state could enable or disable certain parts of the system.

For example,

if( g_GameState == GAME_STATE_PLAYING ){    UpdateWorld();    RenderWorld();}ScreenManager::Update();ScreenManager::Render();



So basically, you update and render the world only if a game is in progress. Also every frame you render what's in the ScreenManager... The screen manager could contain a stack of Screens (which are pushed or popped as necessary)... So this little code snippet could be used for either the title screen, or the game itself.

For the title screen, you would create a class derived from Screen, and push it on to the screen stack. That's it- now the code I posted above will take care of showing the main screen. When you click on "Start game" from the title screen, then you could pop the title screen, and push on the screen which contains the game's HUD, and set the game state to GAME_STATE_PLAYING.

I dunno if this is the best way to do it, but it works :) It was used on a commercial RTS game of several hundred thousand lines of code so I don't think you'd run into any problems with it...

roos
I implement my game loop using the following method:

1) Have a abstract class called GameMode which all of the "game modes" inherit from (map mode, boot mode, battle mode, etc). There are two virtual functions to this class, called Update() and Draw().

2) Each game mode class inherits from the GameMode class and implements the Update() and Draw() functions

3) keep a stack of GameModes, where the GameMode on top is the currently active mode.

4) Call the Update() and Draw() functions on the GameMode on top of the stack.


Here's the main game loop with this method:

	// This is the main loop for the game. The loop iterates once every frame.	while (SettingsManager->not_done) {		// 1) Draws the screen to the back buffer		ModeManager->GetTop()->Draw();				// 2) Displays the new frame on the screen		VideoManager->Render();				// 3) Process all new events		EventHandler();				// 4) Updates the game status		ModeManager->GetTop()->Update(SettingsManager->UpdateTime());		      		// 5) Reset our key and joystick press and release flags		SettingsManager->ResetInputFlags();	} // while (SettingsManager.not_done) 


And that's it. I pass the number of milliseconds that have passed since the last loop to the Update() function, because our engine uses time-based movement to compute how much/how far to update the game's status.


I can provide the definitions/implementations of the ModeManager, GameMode, and SettingsManager if anyone is interested in it.

Hero of Allacrost - A free, open-source 2D RPG in development.
Latest release June, 2015 - GameDev annoucement

I basically use the stack.

I keep a stack of States, where each state has its own Input, Update and Render functions, much like Roos describes. Keeps everything very organized, and it works like you would expect a game to.

start game:

-push menu state to stack
-input/update/display menu
-player chooses options
-push option state to stack
-input/update/display options
-player presses escape (or whatever)
-pop options from stack
-input/update/display menu
-player chooses to play game
-push game state to stack
-input/update/display game
-player has enough, so presses F1 (or whatever)
-pop game state from stack
-input/update/display menu
-player chooses quit
-pop all, quit




Don't be afraid to be yourself. Nobody else ever will be.
Here's a straight C way of doing it with callbacks. There is no processing done until you actually change the state...

typedef void (*TickCallback)();BOOL         gbRunning = TRUE;TickCallback gpfTickCB = IntroTick;enum GameState{  GAMESTATE_INTRO,  GAMESTATE_GAME,  GAMESTATE_MENU,}void SetState(GameState eState){  switch(eState)  {    case GAMESTATE_INTRO:    {      gpfTickCB = IntroTick;      break;    }    case GAMESTATE_GAME:    {      gpfTickCB = GameTick;      break;    }    case GAMESTATE_MENU:    {      gpfTickCB = MenuTick;      break;    }  }}void IntroTick(){  printf("intro");  if (bExit)  {    SetState(GAMESTATE_GAME);  }}void GameTick(){  // game tick etc..}void MenuTick(){  // menu tick etc..}void main(){  while (gbRunning)  {    gpfTickCB();  }}


Of course, you probably want to handle things like shutting down and initialization when you change the state. But you get the idea...
do unto others... and then run like hell.
Personally I like to use function pointers :)
Quote:Original post by X-0ut
Personally I like to use function pointers :)

That makes a lot of sense, since you avoid the classic switch statement.

My first attempt of a game was in Java, and since there aren't function pointers there, I "registered" States in the main game object. The states are an implementation of a common interface that have update(), render(), process() -or whatever you want to call it- methods. Every State change registers the actual state-object the game is changing to, so the task os processing a state is a simple call to the methods of a member of the game object.
As far as I know, function pointers are not neccessairely faster than switch statements. But they look nicer :)

I use 2 threads for my games, the main thread for drawing, so the framerate can be as high(or low) as possible, and one for game logic, which runs at constant speed, e.g. 50 FPS.

I also use a architecture of game states, all inherited from one abstract base game state class, and every game state has a method "draw" , called by the main thread and one "process", called by the game logic thread.
- Benjamin Block

This topic is closed to new replies.

Advertisement