|
|
controlling your game
Delphi programming techniques(3) |
|
|
This articles gives some suggestions how to control your (board) game.
Illustration below shows the layout of such a game, connect4 or whatever.
There is a board, where pieces are placed by the players.
A game is started by pressing the "start" button.
A game is ended by pressing the "new game" button.
Properties as level or strategy are selectable by the "property" buttons.
First of all, procedures have to be written to paint or erase the board.
These are low level paint procedures.
Next, data structures must be designed, such as
- a two dimensional array representing the board state
- a one dimensional array holding the list of moves
- additional arrays of constants that control game behaviour
note: the low level paint routines must not use the arrays, which are higher in level.
Reason is, that a change of the data structures during the design phase does not need a redesign
of the low level paint routines.
Next, the high-level procedures must be designed.
They take care of the moves by altering the arrays and calling the low level paint routines.
The high level procedures are called by events from mouse or keyboard.
Problem here is, that actions originating from such events depend on the situation of the game.
So, together with the data structures, the game states must be defined
type TGameState = (gsInitializing, gsMenu, gsPlayerMove, gsComputermove, gsPlayerWin, gsComputerwin, gsEnd);
var GameState : TGameState;
gsInitializing | during startup of game. Initialize tables such as clearing the moves list. |
gsMenu | allow for property selections between games. |
gsPlayerMove | allow mouse or keyboard events to define player move. |
gsComputerMove | block events, while computer calculates/displays it's move. |
gsPlayerWin | game end by winning of player. |
gsComputerWin | game end by winning of computer. |
gsEnd | game end, board full, no winner. |
Besides the mouse and keyboard events, it is convenient to consider the control buttons as well as events.
type TGameEvent = (geInitDone, geStart, geNewGame, gePropertyChange, gePlayermoveDone, geComputermovedone);
geInitDone | initialization of tables is completed. |
geStart | the start button was pressed. |
geNewGame | the new game button was pressed. |
gePropertychange | a property button was pressed. |
gePlayerMoveDone | the player has issued a move. |
geComputerMoveDone | the computer has finished it's move. |
Above events are best handled by nested case statements.
This is how the structure looks:
procedure GameControl(gev : TGameEvent);
begin
case GameState of
gsInitializing : case gev of
geInitDone : setmenumode;
end;
gsMenu : case gev of
geStart : startgame;
geNewGame : setmenumode;
gePropertyChange : setproperties;
end;
gsPlayerMove : case gev of
geNewGame : setmenumode;
gePlayermoveDone : docomputermove;
end;
gsComputermove : case gev of
geComputermovedone : doplayermove;
end;
gsPlayerWin : case gev of
geNewGame : setmenumode;
end;
gsComputerwin : case gev of
geNewGame : setmenumode;
end;
gsEnd: case gev of
geStart: startgame;
geNewGame : setmenumode;
end;
end;
So, the procedures setmenumode, startgame, docomputermove, etc are triggered by
events that are redirected according to the game state.
They call the hi-level procedures to do the job, such as enabling/disabling property buttons,
triggering timers to accomplish a move.
They direct keyboard and mouse events allowing the the player to move.
Once the player has moved, a call to gamecontrol with gev = gePlayerMoveDone
informs gamecontrol, which then must call a procedure to test for win or end situation
or switch the gamestate to gsComputerMove.
Below is a coarse structure of a typical board game where the player plays against the computer.
The proc1..n procedures are the high level helpers of the gameControl routine to change gamestates,
alter the game data structures as moves are done, enable/disable property selection buttons,
or display informative messages to the player.
|
|