Code archives/Miscellaneous/Game state engine
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
You can use this code to split the game into different states. Extend GenericState into things like "StatePlay", "StateMenu", "StateGamePaused", etc and just call "GameState.Switch( new StatePlay )" when you want to jump from one state to another. Here is a quick example: Strict ' Include the goodies Include "gamestate.bmx" Graphics 800,600,0 ' Switch to the menu state GameState.Switch( New StateMenu ) ' Go! GameState.Run() End ' We're done now. '------------------------------------------------------------ '-------------------- Our extended states '------------------------------------------------------------ ' Create a new kind of state Type StateMenu Extends GenericState Method startup() Print "Loading menu..." EndMethod Method update() If KeyHit( KEY_1 ) Then GameState.switch( New StatePlay ) ' Player wants to play a game EndIf If KeyHit( KEY_2 ) Then GameState.ExitState() ' Exit this state. EndMethod Method draw() Cls DrawText "Game menu 2000 ultra power", 50,50 DrawText "1. Play the game", 50,80 DrawText "2. Quit", 50,100 Flip ; FlushMem EndMethod Method shutdown() Print "Removing menu stuff..." EndMethod Method on_hold() Print "Menu is paused while another state is running." EndMethod Method resume() Print "The menu is back in bussiness!" EndMethod EndType Type StatePlay Extends GenericState Field x,y, xv,yv Field paused_time Method startup() Print "Loading game..." x = Rand(0,800) y = Rand(0,600) xv = Rand(0,1) yv = Rand(0,1) EndMethod Method update() If KeyHit( KEY_ESCAPE ) Then GameState.ExitState() ' Player doesn't want to play anymore... If KeyHit( KEY_P ) Then GameState.Switch( New StatePause ) ' Pause the game If xv Then x:+1 Else x:-1 EndIf If yv Then y:+1 Else y:-1 EndIf If x < 0 Or x > 800 Then xv = Not xv If y < 0 Or y > 600 Then yv = Not yv EndMethod Method draw() Cls DrawRect( x-5,y-5,11,11 ) DrawText "Press Escape to quit, P to pause the game", 0,0 Flip ; FlushMem EndMethod Method shutdown() Print "Game is no more..." EndMethod Method on_hold() Print "Game paused while another state is running." ' Just for fun, save the millisecs() paused_time = MilliSecs() EndMethod Method resume() Print "Game resumed" ' For how long was we on hold? Print "Your little intermission lasted for "+(MilliSecs()-paused_time)+" milliseconds." EndMethod EndType Type StatePause Extends GenericState Method startup() Print "Game paused." SetBlend ALPHABLEND SetColor 0,0,0 SetAlpha 0.5 DrawRect( 0,0, 800,600 ) SetAlpha 1 SetColor 255,255,255 ' Draw the paused message here, only need to draw it once. DrawText "Tea time, eh? Press P to resume.", 100,100 Flip ; FlushMem FlushKeys() EndMethod Method update() ' Just wait for the right key to be pressed If KeyHit( KEY_P ) Then GameState.ExitState() ' Exit the pause state and go back to the play state EndMethod Method draw() ' No need to draw anything. It was done during startup EndMethod Method shutdown() Print "Unpaused." EndMethod Method on_hold() Print "Pause state paused? Funny that..." ' Not that crazy after all. Many games have a game menu that can be reached during a paused game EndMethod Method resume() Print "The pause state is resumed." EndMethod EndType And here you have gamestate.bmx: | |||||
' make a new type that extends this one. Overload the methods. Type GenericState ' Overload this one and put startup code here (loading images, sounds, etc) Method startup() EndMethod ' No drawing here! Only user input and other behind-the-scene stuff Method update() EndMethod ' Draw things in this one. But no user input or logic code! Method draw() EndMethod ' Save highscore/nullify variables/scream like a banshee Method shutdown() EndMethod ' Called when the engine switches to a new state. Method on_hold() EndMethod ' Called when the engine is done with the other state and switches back t this one Method resume() EndMethod EndType Type GameState Global state_list:TList Global current_state:GenericState Function Switch( new_state:GenericState ) If Not state_list Then state_list = CreateList() state_list.addlast( new_state ) If current_state Then current_state.on_hold() new_state.startup() current_state = new_state EndFunction ' Called by the running state when it doesn't want to play anymore Function ExitState() If Not state_list Then RuntimeError("ExitState should only be called by running states!") current_state.shutdown() state_list.remove( current_state ) If state_list.Count() > 0 Then current_state = GenericState( state_list.last() ) current_state.resume() EndIf EndFunction Function Run() If Not state_list Then RuntimeError("Switch to a new game state before calling GameState.Run()") While state_list.Count() > 0 current_state.update() current_state.draw() Wend EndFunction EndType |
Comments
| ||
The logic and drawing code is separated in the states so that you could implement frame skipping in GameState.Run(). If you want to use delta time then just do it in the update() method of your states. Hope you will find this useful. |
| ||
Oops, double post. deleted. |
Code Archives Forum