This tutorial will enable you to out a more advanced Heads Up Display (HUD) in your GTest derived game than my previous one. Again this is based on Ewens initial work. The features of this new HUD are:

  1. Health Dsiplay (and icon)
  2. Armor Display (and icon)
  3. Weapon Dsiplay (and ammo icon)

This tutorial requires that you know your way around GTest, although it should be fairly easy for beginners to pick it up.

Here is a screenshot of the new HUD you will be creating.

 



[The code below will enable you to create this exact HUD].

First, you will need to download the two files, Hud.c and Hud.h (zipped at the bottom of the page). Then you can start by setting up the HUD as in my previous tutorial (Please Note: there are some modifications):

In GENVS.C you must add a line near the beginning of the file to include HUD.H

Line 35: #include "HUD.h"

Next add a pointer to a HUD object (and a rectangle object we'll use to position the HUD), about line 72:

// Misc objects
static Console_Console *Console;
Host_Host *Host;

geSound_System *SoundSys;
HUD *theHUD;
geRect gR = {0,0,0,0};

Now we need some changes to the WinMain function, to set the clipping rectangle of the HUD and to create the HUD object. First we will need to declare two integers, at the very top of WinMain:

int Width, Height;

Then, at around about line 415 or so (just before the while (Running) statement):

 


#if 1
// <>
geEngine_SetGamma(Engine, UserGamma);
#endif

QueryPerformanceFrequency(&Freq);
QueryPerformanceCounter(&OldTick);


// Hud
VidMode_GetResolution(VidMode,&Width,&Height);

gR.Left = 0;
gR.Top = 0;
gR.Right = Width;
gR.Bottom = Height;

gHUD = CreateClientHUD(Engine, &gR); // create the HUD object


//SetCapture(GameMgr_GethWnd(GMgr));
ShowCursor(FALSE);

#ifdef CLIP_CURSOR
{

(Note - now the Hud resizes to fit your screen size).


Finally, we need to destroy the HUD on shutdown by modifying the ShowdownAll function:

//=====================================================================================
// ShutdownAll
//=====================================================================================
void ShutdownAll(void)
{
ReleaseCapture();
ShowCursor(TRUE);

....

// Free each object (sub objects are freed by their parents...)

if (MenusCreated)
{
Text_Destroy();
GMenu_Destroy();
MenusCreated = GE_FALSE;
}

// Hud
DestroyClientHUD(theHUD);

if (Host)
{
Host_Destroy(Host);
Host = NULL;
}

....etc.

In Client.C you must add a line near the beginning of the file to include HUD.H

Line 28:. #include "HUD.h"

After the includes, you must add a line to make a reference to theHUD object in GENVS.C:

Line 35: extern HUD *theHUD;

Next, you must add one line of code to the Client_RenderFrame function:

//=====================================================================================
// Client_RenderFrame
//=====================================================================================
geBoolean Client_RenderFrame(Client_Client *Client, float Time)
{
assert(Client_IsValid(Client) == GE_TRUE);

if (Client->NetState != NetState_WorldActive) // If no world currently set, then return...
return GE_TRUE;

if (!RenderWorld(Client, Client->GMgr, Time))
GenVS_Error("Client_RenderFrame: RenderWorld failed.\n");

if (Client->MultiPlayer)
{
if (!PrintClientScores(Client))
GenVS_Error("Client_RenderFrame: PrintClientScores failed.\n");
}

PrintCrossHair(Client);
UpdateStatusBar(Client);
ScreenBorderHack(Client);

// Hud
if (!DrawHUD(theHUD, Client)) // this is where we draw the HUD
return GE_FALSE;

return GE_TRUE;
}

 


Now, open up GMain.c and near the top, include the hud.h file

#include "HUD.h"

then beneath this, reference the hud you created in GenVS.c (It doesn't matter that this one is called gHud rather than theHud, it is just for convienience).

extern HUD *gHUD;

Now this is a tricky part. In my modified GTest, I have already added kodjis drowing code. I will restate it here so it is obvious how I modified it, but all credit for the pink code goes to him. All this happens in the Client_Control() function

 


...

// Get a box a little bigger than the player for doors, etc...
CMins = Player->Mins;
CMaxs = Player->Maxs;

CMins.X -= 100;
CMins.Y -= 10;
CMins.Z -= 100;
CMaxs.X += 100;
CMaxs.Y += 10;
CMaxs.Z += 100;
CameraMins= Player->Mins;
CameraMaxs = Player->Maxs;

// Start Drowning Code
CameraMaxs.X -= 100;
CameraMaxs.Y -= 10 ;
CameraMaxs.Z -= 100;
CameraMins.X += 100;
CameraMins.Y += 10;
CameraMins.Z += 100;

if (geWorld_GetContents(World,&Player->XForm.Translation, &CameraMins, &CameraMaxs,GE_COLLIDE_MODELS, 0, NULL, NULL, &Contents))
{

// You could play an 'underwater' sound here.
Player->TimeInWater += Time;
}

else if (Player->TimeInWater >= 7.0f)//player's head is no longer under water
{
if (Player->State == PSTATE_InWater)//Player's body is inwater
{

gHUD->ShowWarningIcon = GE_FALSE;
Player->TimeInWater = 0.0f;
GenVSI_SetClientHealth(VSI,Player->ClientHandle, Player->Health);
GenVSI_PlaySound(VSI,SOUND_INDEX_PLAYER_BREATH,&Player->XForm.Translation);
}
}
else Player->TimeInWater =0.0f;

if (Player->TimeInWater > 10.0f)
{

// Show warning on HUD
gHUD->ShowWarningIcon = GE_TRUE;
gHUD->WarningType = DMG_TYPE_DROWN;

Player->Health -= 10;
GenVSI_SetClientHealth(VSI, Player->ClientHandle,Player->Health);
Player->TimeInWater = 7.0f;
GenVSI_PlaySound(VSI,SOUND_INDEX_PLAYER_GASP,&Player->XForm.Translation);
}

if (Player->Health <= 0)
{

gHUD->ShowWarningIcon = GE_FALSE;
GenVSI_PlaySound(VSI,SOUND_INDEX_DIE,&Player->XForm.Translation);
Player->Control = Player_Drowned;
}

// End Drowning Code

if (geWorld_GetContents(World, &Player->XForm.Translation, &CMins, &CMaxs, GE_COLLIDE_MODELS, 0, NULL, NULL, &Contents))
{
if (Contents.Model)
{
GPlayer *TPlayer;

TPlayer = (GPlayer*)geWorld_ModelGetUserData(Contents.Model);

...

 


For the rest of the drowning code, please goto kodjis original tutorial (see the programming section on the World of Genesis).

Basically, what this modification does, is if the player is underwater for too long, an icon flashes on the top of the screen warning them, and take 10 off of their health. The icon is drawn in our new Hud.c file, which is as follows:

 



/******************************************************************************/
/* Hud.c */
/* */
/* Author: Ewen Vowels, David Wulff */
/* Description: HUD implementation */
/* */
/* Copyright (c) 1999, 2000, Battleaxe Studios; All Rights Reserved. */
/* ______ __ __ ___ __ __ __ __ __ _____ __ */
/* / ____/ / / / / / _ \ / / / / / / / / / / / ___ \ / / */
/* / /___ / / / / / /_\ \ / / / / / / / / / / / /__/ / / / */
/* /___ / / / / / / ___ / / / / / / / / / / / / __ / / / */
/* ____/ / / /__/ / / / / / \ \/ / / / \ \/ / / / / / / /___ */
/* /_____/ /______/ /_/ /_/ \__/ /_/ \__/ /_/ /_/ /_____/ */
/* */
/* www.bttlxe.co.uk */
/******************************************************************************/
#pragma warning ( disable : 4013 4047 )

#include <Windows.h>
#include <assert.h>
#include "Genesis.h"

#include "HUD.h"
#include "Globals.h"

#include "Ram.h"
#include "GenVSI.H"
#include "Client.H"
#include "Host.H"
#include "Text.h"

#define ItemWidth 20
#define ItemHeight 20

extern geVFile *PakFS; // Pak File
extern geVFile *MainFS; // App Folder

geBoolean AmmoHack = GE_FALSE;

HUD* CreateClientHUD(geEngine *Engine, geRect *Location)
{
HUD *hud = malloc(sizeof(HUD)); // create the memory for the HUD

assert(hud);

hud->Screen = Location;

Location->Top = Location->Bottom - 25;

hud->Engine = Engine; // get a copy of the engine object
hud->Location = Location; //store the location
hud->Bitmap = geBitmapUtil_CreateFromFileAndAlphaNames(PakFS, "bttlxe\\gfx\\hud\\hud_01.bmp", "bttlxe\\gfx\\hud\\hud_01.bmp");

//geBitmap_CreateFromFileName(PakFS, "bttlxe\\gfx\\hud\\hud_01.bmp");
//hud->AlphaBitmap = geBitmap_CreateFromFileName(PakFS, "bttlxe\\gfx\\hud\\hud_01a.bmp");

// geBitmap_SetColorKey(hud->Bitmap, GE_TRUE, 100, GE_FALSE);

// geBitmap_SetAlpha(hud->Bitmap, h->AlphaBitmap);

geEngine_AddBitmap(hud->Engine, hud->Bitmap);

return hud;
}

geBoolean DestroyClientHUD(HUD * hud)
{
if (hud->Bitmap)
{
assert(hud->Engine);
geEngine_RemoveBitmap(hud->Engine, hud->Bitmap);
}

assert(hud);

free(hud); // free the memory

return GE_TRUE;
}

geBoolean DrawHUD(HUD * hud, Client_Client *client)
{
Client_ClientInfo *clientInfo;

assert(hud->Engine);

clientInfo = client->ClientInfo;

if (!clientInfo->Active)
return GE_TRUE;

// Call the drawing functions:
if (!DrawWarningDisplay(hud, client))
return GE_FALSE;

if (!DrawWeaponDisplay(hud, client))
return GE_FALSE;

if (!DrawDamageDisplay(hud, client))
return GE_FALSE;

if (!DrawCrosshair(hud, client))
return GE_FALSE;

return GE_TRUE;
}

geBoolean DrawWeaponDisplay(HUD * hud, Client_Client *client)
{
Client_ClientInfo *clientInfo;
geRect textClip, sepClip;
int32 remainder, health;
int32 armor;
uint32 Ammo;
geBoolean HasItem;
int32 hack;

assert(hud->Engine);

clientInfo = client->ClientInfo;

if (!clientInfo->Active)
return GE_TRUE;

// set up seperating lines
sepClip.Top = 50;
sepClip.Bottom = 74;
sepClip.Left = 512-2;
sepClip.Right = 512;

//===================================================================
// Draw the Health Dsiplay
//===================================================================
textClip.Top = ItemHeight;
textClip.Bottom = 2 * ItemHeight;
textClip.Left = 0;
textClip.Right = ItemWidth;

if (!geEngine_DrawBitmap(hud->Engine, hud->Bitmap, &textClip, hud->Location->Left + 5, hud->Location->Top))
return GE_FALSE;

textClip.Top = 0;
textClip.Bottom = ItemHeight;
health = clientInfo->Health;
remainder = health / 100;

if (remainder > 0) // only display the first digit if health >= 100
{
textClip.Left = remainder * ItemWidth;
textClip.Right = remainder * ItemWidth + ItemWidth;

if (!geEngine_DrawBitmap(hud->Engine, hud->Bitmap, &textClip, hud->Location->Left + ItemWidth + 5, hud->Location->Top))
return GE_FALSE;
}

health = health % 100;
remainder = health / 10;
textClip.Left = remainder * ItemWidth;
textClip.Right = remainder * ItemWidth + ItemWidth;

if (!geEngine_DrawBitmap(hud->Engine, hud->Bitmap, &textClip, hud->Location->Left + 2*ItemWidth + 5, hud->Location->Top))
return GE_FALSE;

health = health % 10;
remainder = health;
textClip.Left = remainder * ItemWidth;
textClip.Right = remainder * ItemWidth + ItemWidth;

if (!geEngine_DrawBitmap(hud->Engine, hud->Bitmap, &textClip, hud->Location->Left + 3*ItemWidth + 5, hud->Location->Top))
return GE_FALSE;

// Draw the seperating line between items
if (!geEngine_DrawBitmap(hud->Engine, hud->Bitmap, &sepClip, hud->Location->Left + 5*ItemWidth + 10, hud->Location->Top - 3))
return GE_FALSE;

//===================================================================
// Draw the Armor Dsiplay
//===================================================================

textClip.Top = ItemHeight;
textClip.Bottom = 2 * ItemHeight;
textClip.Left = ItemWidth;
textClip.Right = 2 * ItemWidth;

if (!geEngine_DrawBitmap(hud->Engine, hud->Bitmap, &textClip, hud->Location->Left + 6*ItemWidth + 5, hud->Location->Top))
return GE_FALSE;

textClip.Top = 0;
textClip.Bottom = ItemHeight;

// For some reason, a 32 bit value is being assigned to the armor, so subtract it here:
hack = 32768;
armor = client->Inventory[ITEM_ARMOR] - hack;
remainder = armor / 100;

if (remainder > 0) // only display the first digit if armor >= 100
{
textClip.Left = remainder * ItemWidth;
textClip.Right = remainder * ItemWidth + ItemWidth;

if (!geEngine_DrawBitmap(hud->Engine, hud->Bitmap, &textClip, hud->Location->Left + 7*ItemWidth + 5, hud->Location->Top))
return GE_FALSE;
}

armor = armor % 100;
remainder = armor / 10;
textClip.Left = remainder * ItemWidth;
textClip.Right = remainder * ItemWidth + ItemWidth;

if (!geEngine_DrawBitmap(hud->Engine, hud->Bitmap, &textClip, hud->Location->Left + 8*ItemWidth + 5, hud->Location->Top))
return GE_FALSE;

armor = armor % 10;
remainder = armor;
textClip.Left = remainder * ItemWidth;
textClip.Right = remainder * ItemWidth + ItemWidth;

if (!geEngine_DrawBitmap(hud->Engine, hud->Bitmap, &textClip, hud->Location->Left + 9*ItemWidth + 5, hud->Location->Top))
return GE_FALSE;

//===================================================================
// Ammo Display (Type)
//===================================================================
Ammo = client->Inventory[client->CurrentWeapon];

HasItem = (Ammo & (1<<15));

Ammo &= 0xff;

if (HasItem)
{
textClip.Top = 0; // numbers are the top row of the HUD ITEMS texture
textClip.Bottom = ItemHeight;

remainder = Ammo / 100;
if (remainder > 0) // only draw the first digit if necessary
{
AmmoHack = GE_TRUE;

textClip.Left = remainder * ItemWidth;
textClip.Right = remainder * ItemWidth + ItemWidth;

if (!geEngine_DrawBitmap(hud->Engine, hud->Bitmap, &textClip, hud->Location->Right - (10 + 4*ItemWidth), hud->Location->Top))
return GE_FALSE;
}
else
AmmoHack = GE_FALSE;

Ammo = Ammo % 100;
remainder = Ammo / 10;

if (remainder > 0) // only draw the second digit if necessary
{
textClip.Left = remainder * ItemWidth;
textClip.Right = remainder * ItemWidth + ItemWidth;

if (!geEngine_DrawBitmap(hud->Engine, hud->Bitmap, &textClip, hud->Location->Right - (10 + 3*ItemWidth), hud->Location->Top))
return GE_FALSE;
}
else if (AmmoHack != GE_FALSE)
{
textClip.Left = 0;
textClip.Right = ItemWidth;

if (!geEngine_DrawBitmap(hud->Engine, hud->Bitmap, &textClip, hud->Location->Right - (10 + 3*ItemWidth), hud->Location->Top))
return GE_FALSE;
}

Ammo = Ammo % 10;
remainder = Ammo;
textClip.Left = remainder * ItemWidth;
textClip.Right = remainder * ItemWidth + ItemWidth;

if (!geEngine_DrawBitmap(hud->Engine, hud->Bitmap, &textClip, hud->Location->Right - (10 + 2*ItemWidth), hud->Location->Top))
return GE_FALSE;
}
else
{
//if (!Console_XYPrintf(Host->Console, 30, 30, " Ammo: No Weapon"))
// return GE_FALSE;
}

textClip.Top = ItemHeight;
textClip.Bottom = 2 * ItemHeight;

switch(client->CurrentWeapon)
{
case 0: // blaster (will be knife)
{
textClip.Left = 9*ItemWidth;
textClip.Right = 10*ItemWidth;
break;
}
case 1: // handgrenade
{
textClip.Left = 8*ItemWidth;
textClip.Right = 9*ItemWidth;
break;
}
case 2: // rpg
{
textClip.Left = 7*ItemWidth;
textClip.Right = 8*ItemWidth;
//if (!Console_XYPrintf(Host->Console, 30, 31, " Rockets"))
// return GE_FALSE;
break;
}
case 3: // mgun
{
textClip.Left = 4*ItemWidth;
textClip.Right = 5*ItemWidth;
break;
}
case 4: // shotgun
{
textClip.Left = 6*ItemWidth;
textClip.Right = 7*ItemWidth;
break;
}
case 5: // pistol
{
textClip.Left = 3*ItemWidth;
textClip.Right = 4*ItemWidth;
break;
}
case 6: // magnum 357
{
textClip.Left = 3*ItemWidth;
textClip.Right = 4*ItemWidth;
break;
}
default:
{
textClip.Left = 9*ItemWidth;
textClip.Right = 10*ItemWidth;
break;
}
}

// Only draw the ammo icon if the client actually has the weapon.
if (client->Inventory[client->CurrentWeapon] != GE_FALSE)
if (!geEngine_DrawBitmap(hud->Engine, hud->Bitmap, &textClip, hud->Location->Right - (5 + ItemWidth), hud->Location->Top))
return GE_FALSE;

return GE_TRUE;
}

geBoolean DrawWarningDisplay(HUD * hud, Client_Client *client)
{
Client_ClientInfo *clientInfo;
geRect textClip;

assert(hud->Engine);

clientInfo = client->ClientInfo;

if (!clientInfo->Active)
return GE_TRUE;

if (hud->ShowWarningIcon)
{
switch (hud->WarningType)
{
case DMG_TYPE_DROWN:
{
textClip.Left = 260;
textClip.Right = 260 + 50;
break;
}
case DMG_TYPE_BURN:
{
textClip.Left = 260;
textClip.Right = 260 + 150;
break;
}
case DMG_TYPE_FREEZE:
{
textClip.Left = 260;
textClip.Right = 260 + 100;
break;
}
case DMG_TYPE_TOXIC:
{
textClip.Left = 260;
textClip.Right = 260 + 50;
break;
}
case DMG_TYPE_ELECTRIC:
{
textClip.Left = 260 + 210;
textClip.Right = 260 + 250;
break;
}
}

textClip.Top = 0;
textClip.Bottom = 50;

if (!geEngine_DrawBitmap(hud->Engine, hud->Bitmap, &textClip, 20, 20))
return GE_FALSE;
}

return GE_TRUE;
}

geBoolean DrawDamageDisplay(HUD * hud, Client_Client *client)
{
Client_ClientInfo *clientInfo;
GE_Rect Rect;
GE_RGBA Color;

// Filled rect.
Rect.Left = 0;
Rect.Right = 20000;
Rect.Top = 0;
Rect.Bottom = 15000;

// Fill colour.
Color.r = 0.0f;
Color.g = 0.0f;
Color.b = 0.0f;
Color.a = 255.0f;

assert(hud->Engine);

clientInfo = client->ClientInfo;

if (!clientInfo->Active)
return GE_TRUE;
/*
if (hud->ShowDamage)
{
switch (hud->DamageDirection)
{
case DMG_DIR_TOP:
{
Rect->Top = 50;
Rect->Bottom = ;
Rect->Left = 50;
Rect->Right = Width - 50;
break;
}
}

textClip.Top = 0;
textClip.Bottom = 50;
*/
/* if (!geEngine_DrawBitmap(hud->Engine, hud->Bitmap, &textClip, 20, 20))
return GE_FALSE;*/

geEngine_FillRect( hud->Engine, &Rect, &Color ); // Filled rect.
// }

return GE_TRUE;
}

geBoolean DrawCrosshair(HUD * hud, Client_Client *client)
{
Client_ClientInfo *clientInfo;
geRect textClip;
int Width, Height, Left;

assert(hud->Engine);

clientInfo = client->ClientInfo;

if (!clientInfo->Active)
return GE_TRUE;

Width = 20;
Height = 20;
Left = 270;
textClip.Top = 120;
textClip.Bottom = 120 + Height;

switch(client->CurrentWeapon)
{
case 0: // blaster (will be knife)
{
textClip.Left = Left + (6 * Width);
textClip.Right = Left + (7 * Width);
break;
}
case 1: // handgrenade - (no crosshair)
{
textClip.Left = Left - Width;
textClip.Right = Left;
break;
}
case 2: // rpg
{
textClip.Left = Left + (9 * Width);
textClip.Right = Left + (10 * Width);
break;
}
case 3: // mgun
{
textClip.Left = Left + (5 * Width);
textClip.Right = Left + (6 * Width);
break;
}
case 4: // shotgun
{
textClip.Left = Left + (4 * Width);
textClip.Right = Left + (5 * Width);
break;
}
case 5: // pistol
{
textClip.Left = Left + (8 * Width);
textClip.Right = Left + (9 * Width);
break;
}
case 6: // magnum 357
{
textClip.Left = Left + (10 * Width);
textClip.Right = Left + (11 * Width);
break;
}
default:
{
textClip.Left = Left + (8 * Width);
textClip.Right = Left + (9 * Width);
break;
}
}

// Only draw the crosshair if the client actually has the weapon.
if (client->Inventory[client->CurrentWeapon] != GE_FALSE)
if (!geEngine_DrawBitmap(hud->Engine, hud->Bitmap, &textClip,
(hud->Screen->Right / 2) - (Width / 2),
(hud->Screen->Bottom / 2) - (Height / 2) - 10))
return GE_FALSE;

return GE_TRUE;
}

#pragma warning ( default : 4013 4047 )

 


You will need to change the available weapons to match those in your game.

The hud.h file is as follows:

 



/******************************************************************************/
/* Hud.h */
/* */
/* Author: Ewen Vowels, David Wulff */
/* Description: HUD defines and definitions */
/* */
/* Copyright (c) 1999, 2000, Battleaxe Studios; All Rights Reserved. */
/* ______ __ __ ___ __ __ __ __ __ _____ __ */
/* / ____/ / / / / / _ \ / / / / / / / / / / / ___ \ / / */
/* / /___ / / / / / /_\ \ / / / / / / / / / / / /__/ / / / */
/* /___ / / / / / / ___ / / / / / / / / / / / / __ / / / */
/* ____/ / / /__/ / / / / / \ \/ / / / \ \/ / / / / / / /___ */
/* /_____/ /______/ /_/ /_/ \__/ /_/ \__/ /_/ /_/ /_____/ */
/* */
/* www.bttlxe.co.uk */
/******************************************************************************/
#ifndef _HUD_H
#define _HUD_H

#include <Windows.h>

#include "Genesis.h"
#include "Ram.h"
#include "Client.H"
#include "Host.H"
#include "Text.h"
#include "Host.h"
#include "Server.h"
#include "GPlayer.h"
#include "GenVSI.h"

#ifdef __cplusplus
extern "C" {
#endif


typedef struct HUD
{
geEngine *Engine;
geRect *Location;
geRect *Screen;
geBitmap *Bitmap;
geBitmap *AlphaBitmap;
geBoolean ShowWarningIcon;
int WarningType; // Water, heat, etc...
geBoolean ShowWeaponIcon;
int WeaponNumber;
geBoolean WeaponDisabled;
geBoolean ShowDamage;
int DamageDirection;
int DamageAmount;

} HUD;

HUD *CreateClientHUD(geEngine *Engine, geRect *Location);
geBoolean DestroyClientHUD(HUD * hud);
geBoolean DrawHUD(HUD * hud, Client_Client *client);
geBoolean DrawWarningDisplay(HUD * hud, Client_Client *client);
geBoolean DrawWeaponDisplay(HUD * hud, Client_Client *client);
geBoolean DrawDamageDisplay(HUD * hud, Client_Client *client);
geBoolean DrawCrosshair(HUD * hud, Client_Client *client);
geBoolean DrawPickups(HUD * hud, Client_Client *client);

#ifdef __cplusplus
}
#endif

#endif

 


I have included a file called globals.h at the top of hud.c, which contains all of the defines for the hud damage types, etc:

 



/******************************************************************************/
/* Globals.h */
/* */
/* Author: David Wulff */
/* Description: Global defines and definitions */
/* */
/* Copyright (c) 1999, 2000, Battleaxe Studios; All Rights Reserved. */
/* ______ __ __ ___ __ __ __ __ __ _____ __ */
/* / ____/ / / / / / _ \ / / / / / / / / / / / ___ \ / / */
/* / /___ / / / / / /_\ \ / / / / / / / / / / / /__/ / / / */
/* /___ / / / / / / ___ / / / / / / / / / / / / __ / / / */
/* ____/ / / /__/ / / / / / \ \/ / / / \ \/ / / / / / / /___ */
/* /_____/ /______/ /_/ /_/ \__/ /_/ \__/ /_/ /_/ /_____/ */
/* */
/* www.bttlxe.co.uk */
/******************************************************************************/
#pragma warning ( disable : 4244 )

#ifndef GLOBALS_H
#define GLOBALS_H

// Damage Types
#define DMG_TYPE_DROWN 1
#define DMG_TYPE_BURN 2
#define DMG_TYPE_TOXIC 4
#define DMG_TYPE_FREEZE 8
#define DMG_TYPE_ELECTRIC 16

#define DMG_DIR_TOP 1
#define DMG_DIR_BOTTOM 2
#define DMG_DIR_LEFT 4
#define DMG_DIR_RIGHT 8
#define DMG_DIR_FRONT 16
#define DMG_DIR_BACK 32

#pragma warning ( default : 4244 )

#endif

 


Now, all that is left to do is to compile GTest. Inevitably you will get those small errors where I have forgotten to tell you that I have customised something, but these should not be to hard to sort out.

You are free to use this code in any way that you want. I do not require you to credit me (unless you really want to :-) ), but Ewen would like a mention in the credits as being the original brain behind the idea.

Any problems you find with this source (yes, you will find it is not fineshed - I started to add damage displays, but got nowhere fast, so I left them commented out above - if you really want to finish them, please could you email me the modified files so I can use the source), can be emailed to me here: dwulff@bttlxe.co.uk (please indicate what tutorial you are refering to).

Now, here are the zipped files. Included are the two hud.* files, but not the globals file (you can do that yourself). I have also added a larger hud icons bitmap. You can grap the files here.

 

Until next time,

- David Wulff.