Bolo

From WinBolo

(Difference between revisions)
Jump to: navigation, search
(backend.c)
(screen.c)
Line 116: Line 116:
The main simulation loop. Must be called every 20ms. Frontends must repeatedly call if it falls behind processing. It runs everything in the game world from moving the tank, refueling a tank calculating base refueling, growing trees, moving the LGM. This is done by calling the Update() function to each of the ADTs within the game world. Note: If the backend is a client in a multiplayer game some of the ADT's may do nothing.
The main simulation loop. Must be called every 20ms. Frontends must repeatedly call if it falls behind processing. It runs everything in the game world from moving the tank, refueling a tank calculating base refueling, growing trees, moving the LGM. This is done by calling the Update() function to each of the ADTs within the game world. Note: If the backend is a client in a multiplayer game some of the ADT's may do nothing.
 +
 +
<pre>
 +
/*********************************************************
 +
*NAME:          screenKeysTick
 +
*AUTHOR:        John Morrison
 +
*CREATION DATE: 8/2/99
 +
*LAST MODIFIED: 27/11/99
 +
*PURPOSE:
 +
* This function is called whenever a update keys tick
 +
* happens (twice the game tick length)
 +
*
 +
*ARGUMENTS:
 +
* tb      - The combinations of tank buttons being pressed
 +
* isBrain - TRUE if brain is running. Other parameter is
 +
*          ignored
 +
*********************************************************/
 +
void screenKeysTick(tankButton tb, bool isBrain);</pre>
 +
 +
This function was added in [[Version History#Version 1.04|version 1.04]] of WinBolo. It is called very other 10ms to allow for smoother aiming of the tank. Its a cut down version of ''screenGameTick();'' that just updates the tanks direction.
 +
 +
<pre>/*********************************************************
 +
*NAME:          screenUpdate
 +
*AUTHOR:        John Morrison
 +
*CREATION DATE: 28/10/98
 +
*LAST MODIFIED: 21/01/01
 +
*PURPOSE:
 +
*  Updates the screen. Takes numerous directions
 +
*
 +
*ARGUMENTS:
 +
*  value - Pointer to the starts structure
 +
*********************************************************/
 +
void screenUpdate(updateType value);</pre>
 +
 +
This function is called when the front end has moved the view up/down/left/right or wishes to refresh the main screen. The function calculates the tiles that are currently in view and creates lists of items (tanks/shells/explosions/lgms) to be draw onto the main screen before calling the front end function ''frontEndDrawMainScreen();'' and then finally cleans up the data. As this call needs to be synchronized performance could be increased by creating a screenPrepareDraw() function that would prepare all the data but allow the rendering to take place outside of the synchronized function.
 +
 +
In the future this function probably will not do the tile calculation as different front ends such as 3D will care what the real terrain is, not what the tile that should be shown is.
 +
 +
 +
 +
Screen.c also contains many functions for setting values from the front end or getting data back to display. E.g:
 +
<pre>
 +
void screenShowMessages(BYTE msgType, bool isShown);
 +
void screenSetAutoScroll(bool isAuto);
 +
bool screenSetPlayerName(char *value);
 +
void screenGetKillsDeaths(int *kills, int *deaths);
 +
void screenSendMessageAllPlayers(char *messageStr);
 +
bool screenSaveMap(char *fileName)
 +
void screenGetMapName(char *value);
 +
BYTE screenGetNumPlayers();
 +
long screenGetGameTimeLeft();
 +
</pre>

Revision as of 14:40, 1 December 2008

The bolo directory contains the backend code for simulating a game world.

#screen.c is the main entry point for client applications to talk to the backend.

The backend is not threadsafe and access to any functions should be syncronized.

Contents

Design

Although WinBolo is not written in C++ the backend has object orientated principles for managing the game world. This is due to the use of abstract data types within each module. (Note not all modules) For instance here is a list of some of pillbox functions:

void pillsCreate(pillboxes *value);
void pillsDestroy(pillboxes *value);
void pillsSetNumPills(pillboxes *value, BYTE numPills);
BYTE pillsGetNumPills(pillboxes *value);
void pillsSetPill(pillboxes *value, pillbox *item, BYTE pillNum);
bool pillsExistPos(pillboxes *value, BYTE xValue, BYTE yValue);
void pillsUpdate(pillboxes *value, map *mp, bases *bs, tank *tnk, shells *shs);

The ADT concept as well as New() and Dispose() macro's for ADT memory management come from Geoff Whales book - Data Structures and Abstraction Using C.


Client vs Server

The backend has code that provides processing for a single player game and game server as well as a dumber client. This is handled by the function threadsGetContext(); which returns TRUE if it is a server performing the action or FALSE if it is a client. Note that a single player game will return FALSE. Single player games need to be able to use some of the server logic to work to work correctly. So the backend will typically contain.

if (threadsGetContext() == TRUE || netGetType() == netSingle) {

The reason these two tests can not be simplified into threadsGetContext() function is they are also used to determine which structures are passed to the modules. Single player games use the client structures memory addresses.


Files

backend.c

Backend.c primary purpose is to switch between server and client functions based upon the current threads game context. In doing so it implements some of the functions of backend.h. For example the backend function screenGetNumNeutralBases(); is implemented:

/*********************************************************
*NAME:          screenGetNumNeutralBases
*AUTHOR:        John Morrison
*CREATION DATE: 21/2/99
*LAST MODIFIED: 21/2/99
*PURPOSE:
* Returns the number of neutral bases
*
*ARGUMENTS:
*
*********************************************************/
BYTE screenGetNumNeutralBases(void) {
  if (threadsGetContext() == FALSE) {
    return clientGetNumNeutralBases();
  }
  return serverCoreGetNumNeutralBases();
}

The reason for this switching module is because of WinBolo's development history. The very first versions were built as a single player clone. The backend functions all started with screen*(); When the game became networkable (around WIP release 8) (todo full version history) the server functions were created using the prefix of serverCore*(); Any backend code that needed to access screen*(); functions could be added into the servercore file. The problem arose when trying to merge the server and client applications into the one binary.

The result was the API (function names) remained screen*(); but backend.c would switch between client*(); and serverCore*(); depending upon thread context.

This could be simplified by creating a game world structure that contains references to each of the ADT memory locations and having a single function to return the correct ADT rather then switching per ADT. The JBolo design uses this design.

screen.c

screen.c is the main entry point to the backend for clients. Overview of key functions:

/*********************************************************
*NAME:          screenLoadMap
*AUTHOR:        John Morrison
*CREATION DATE: 29/10/98
*LAST MODIFIED: 30/01/02
*PURPOSE:
*  Loads a map. Returns if it was sucessful reading the
*  map or not.
*
*ARGUMENTS:
* fileName - File name and path to map to open
*  game - The game type-Open/tournament/strict tournament
*  hiddenMines - Are hidden mines allowed
*  srtDelay    - Game start delay (50th second increments)
*  gmeLen      - Length of the game (in 50ths)
*                (-1 =unlimited)
*  playerName  - Name of the player
*  wantFree    - Should we free the backend after loading
*                Usually TRUE if you only want to check
*                if a map is valid
*********************************************************/
bool screenLoadMap(char *fileName, gameType game, bool hiddenMines, long srtDelay, 
                   long gmeLen, char *playerName, bool wantFree);

Sets up a single player game by loading a map.

void screenDestroy();

Called to shutdown the game simulation and free all memory.

/*********************************************************
*NAME:          screenGameTick
*AUTHOR:        John Morrison
*AUTHOR:        John Morrison
*CREATION DATE: 29/10/98
*LAST MODIFIED: 4/1/00
*PURPOSE:
*  This function is called whenever a game tick occurs.
*
*ARGUMENTS:
* tb        - The combinations of tank buttons being
*             pressed
* tankShoot - Is the fire key being pressed?
* isBrain   - TRUE if a brain is running. Other
*             parameters are ignored.
*********************************************************/
void screenGameTick(tankButton tb, bool tankShoot, bool isBrain);

The main simulation loop. Must be called every 20ms. Frontends must repeatedly call if it falls behind processing. It runs everything in the game world from moving the tank, refueling a tank calculating base refueling, growing trees, moving the LGM. This is done by calling the Update() function to each of the ADTs within the game world. Note: If the backend is a client in a multiplayer game some of the ADT's may do nothing.

/*********************************************************
*NAME:          screenKeysTick
*AUTHOR:        John Morrison
*CREATION DATE: 8/2/99
*LAST MODIFIED: 27/11/99
*PURPOSE:
* This function is called whenever a update keys tick
* happens (twice the game tick length)
*
*ARGUMENTS:
* tb      - The combinations of tank buttons being pressed
* isBrain - TRUE if brain is running. Other parameter is
*           ignored
*********************************************************/
void screenKeysTick(tankButton tb, bool isBrain);

This function was added in version 1.04 of WinBolo. It is called very other 10ms to allow for smoother aiming of the tank. Its a cut down version of screenGameTick(); that just updates the tanks direction.

/*********************************************************
*NAME:          screenUpdate
*AUTHOR:        John Morrison
*CREATION DATE: 28/10/98
*LAST MODIFIED: 21/01/01
*PURPOSE:
*  Updates the screen. Takes numerous directions
*
*ARGUMENTS:
*  value - Pointer to the starts structure
*********************************************************/
void screenUpdate(updateType value);

This function is called when the front end has moved the view up/down/left/right or wishes to refresh the main screen. The function calculates the tiles that are currently in view and creates lists of items (tanks/shells/explosions/lgms) to be draw onto the main screen before calling the front end function frontEndDrawMainScreen(); and then finally cleans up the data. As this call needs to be synchronized performance could be increased by creating a screenPrepareDraw() function that would prepare all the data but allow the rendering to take place outside of the synchronized function.

In the future this function probably will not do the tile calculation as different front ends such as 3D will care what the real terrain is, not what the tile that should be shown is.


Screen.c also contains many functions for setting values from the front end or getting data back to display. E.g:

void screenShowMessages(BYTE msgType, bool isShown);
void screenSetAutoScroll(bool isAuto);
bool screenSetPlayerName(char *value);
void screenGetKillsDeaths(int *kills, int *deaths);
void screenSendMessageAllPlayers(char *messageStr);
bool screenSaveMap(char *fileName)
void screenGetMapName(char *value);
BYTE screenGetNumPlayers();
long screenGetGameTimeLeft();
Personal tools