Monday, 16 April 2012

Game State

Currently the program just drops us into the action, where a real game would first perhaps go through and intro sequence, show some titles and then present a menu of options.

Since the main loop runs continuously so that the screen is refreshed regularly, it needs a way to determine what features need to be used, and how they are handled.

You wouldn't want the bottom panel to open and close while the intro is running or the user is selecting from a menu.

This is all handled by the a Game State variable, which holds a value that indicates what state the game is in.

Since we are going to need other game related information to be stored, it makes sense to use a new user defined type for this, which will be called GameType.
type GameType
   state
   level
endtype
Initially this just includes a couple of fields for the current state and level.

The states are defined using constants.
#constant STATE_SETUP   0
#constant STATE_INTRO   1
#constant STATE_DEMO    2
#constant STATE_MENU    3
#constant STATE_RUNNING 4
#constant STATE_EXIT    99
The states used are just examples and will probably change over time as new features are added.

A global variable game is initialised at the start of the new Initialise() function.
function Initialise()
   // Prepare Globals
   global game as gameType
      game.level = 0
      game.state = SetGameState( STATE_SETUP )
Which calls a SetGameState() function, which is used to set the current state.
function SetGameState( thisState )
   game.state = thisState
endfunction
This does not check the state being passed as the parameter, but may do once the states are finalised.

Return functions are added to get the current values for the game global.
// Return Functions - Game

function GameLevel()
endfunction game.level
function GameState()
endfunction game.state
The main loop now has a structure added at the very beginning, which will use different commands depending on the game state. This uses the select and endSelect commands, which contain between them blocks of code surrounded by case and endcase.
do
   LoopStart()
   select GameState()
      case STATE_SETUP
         // Setup Code
      endcase
      case STATE_INTRO
         // Intro Code
      endcase
      case STATE_DEMO
         // Demo Code
      endcase
      case STATE_MENU
         // Menu Code
      endcase
      case STATE_RUNNING
         // Running Code
      endcase
      case STATE_EXIT
         // Exit Code
      endcase
   endselect
At the start of this block, the value after the select command is compared to the values after each of the case statements.  If a match is found, that block of code is used and all others ignored.

If no match is found, then the block identified as case default is used instead.  If there is no case default block, then nothing is used.

The check is made once at the start of the structure and once a block of code is complete, the program jumps to endselect.

It works similar to using multiple if/endif statements, but with only one check.

Initially, the structure has just a comment line to show the location of each code block.

The code we used previously in the main loop is outside this structure and will be run no matter what the game state is.

The next task it to decide which code needs to be run in which game states.
  • Any code run in one state only is moved to the relevant block.
  • Any code run under more than one state is adjusted to check the state is valid.

No comments:

Post a Comment