Game Development Community

dev|Pro Game Development Curriculum

Plastic Gem #41: Health Bar Upgrades

by Anthony Rosenbaum · 08/18/2008 (6:15 am) · 8 comments

Download Code File


i936.photobucket.com/albums/ad202/vincismurf/banner.jpg




Health Bar Upgrades

Difficulty: Easy


In this article we will look at several ways to upgrade the GuiHealthBarHud and so that we have another way of showing health. Most of the code is the same but because TGE and TGEA use different utilities for drawing on the screen we will repeat the final instructions for the rendering section.

TGE - dgl methods
TGEA - GFX methods


TGE
The GuiHealthBarHud, by default it draws a bar representing the percentage of health or energy a player has, will give it the ability draw a numerical value instead of a bar. First let's add some new variables to the class.

1) In guiHealthBarHud class declaration add before the public keyword:

// > pg health enhancement
   bool     mShowValue;
   ColorF   mDropColor;
   Point2I  mDropOffset;
   F32      mHealthChange;
   ColorF   mDamagedColor;
   F32      mDamagedAmt;
   // < pg health enhancement

Now to initialize the new properties in the constructor

2) In GuiHealthBarHud::GuiHealthBarHud() Add: to the bottom


// > pg health enhancement
   mShowValue = false;
   mDropColor.set(0, 0, 0, 1);
   mDropOffset.set(5,5);
   mHealthChange = 0.0f;
   mDamagedColor.set(1, 0, 0, 1);
   mDamagedAmt = 50.0f;
   // < pg health enhancement

We will need to expose them incase we want to adjust them in the editor

3) void GuiHealthBarHud::initPersistFields() add to the bottom


// > pg health enhancement
   addGroup("Value");
   addField( "showValue", TypeBool, Offset( mShowValue, GuiHealthBarHud ) );
   addField( "dropOffset", TypePoint2I, Offset( mDropOffset, GuiHealthBarHud ) );
   addField( "dropColor", TypeColorF, Offset( mDropColor, GuiHealthBarHud ) );
   addField( "damagedColor", TypeColorF, Offset( mDamagedColor, GuiHealthBarHud ) );
   addField( "damagedLimit",TypeF32, Offset( mDamagedAmt, GuiHealthBarHud ) );
   endGroup("Value");
// < pg health enhancement

On to the rendering, first we will do some adjusting of the values if we the showValue property is set to true. follows.

4) Within GuiHealthBarHud::onRender Redesign the mDisplayEnergy if/else block to look like this:

if(mDisplayEnergy)
   {
      mValue = control->getEnergyValue();
   }
   else
   {
      // We'll just grab the damage right off the control object.
      // Damage value 0 = no damage.
	   // > pg health enhancement
	  if(mShowValue)
		mValue = 100 - (100 * control->getDamageValue());
	  else
		mValue = 1 - control->getDamageValue();
	  // < pg health enhancement
   }

Now on to the drawing of the text, notice how we call dglDrawText() twice, first for the drop shadow sencond for the main text and it's color.

5) Replace dglDrawRectFill(rect, mDamageFillColor); with this code block


// > pg health enhancement
   if(mShowValue){

   //change mValue to string
	//char *valueStr  =  (char *)mValue;
		S32 val = (S32)mValue;
		char buf[256];
		dSprintf(buf,sizeof(buf), "%d",val);
		offset.x += (mBounds.extent.x - mProfile->mFont->getStrWidth((const UTF8 *)buf)) / 2;
		offset.y += (mBounds.extent.y - mProfile->mFont->getHeight()) / 2;
	   
		//send call back if the mValue Changes
	   if(mValue != mHealthChange){
		 mHealthChange = mValue;
		 Con::executef(this, 2, "OnHealthChange", buf);
	   }
		ColorF  outColor = mProfile->mFontColor ;
	   if(mValue < mDamagedAmt)
	   {
		   outColor = mDamagedColor;
	   }
		Point2I dropPos;
		dropPos.x = offset.x + mDropOffset.x;
		dropPos.y = offset.y + mDropOffset.y;

	    dglSetBitmapModulation( mDropColor );
		dglDrawText(mProfile->mFont, dropPos, buf);
	    dglClearBitmapModulation();

	    dglSetBitmapModulation( outColor );
		dglDrawText(mProfile->mFont, offset, buf);
	    dglClearBitmapModulation();
   }
	else // < pg health enhancement
		dglDrawRectFill(rect, mDamageFillColor);

TGEA
Alright time for TGEA , luckily MOST of what is above is the same and because of that fact I am only going to replace what needs to be changed. For TGEA simple rewrite the function to use the GFX interface

5) Replace GFX->getDrawUtil()->drawRectFill(rect, mDamageFillColor); with this code block


// > pg health enhancement
   if(mShowValue){

   //change mValue to string
	//char *valueStr  =  (char *)mValue;
		S32 val = (S32)mValue;
		char buf[256];
		dSprintf(buf,sizeof(buf), "%d",val);
		offset.x += (mBounds.extent.x - mProfile->mFont->getStrWidth((const UTF8 *)buf)) / 2;
		offset.y += (mBounds.extent.y - mProfile->mFont->getHeight()) / 2;
	   
		//send call back if the mValue Changes
	   if(mValue != mHealthChange){
		 mHealthChange = mValue;
		 Con::executef(this,  "OnHealthChange", buf);
	   }
	   ColorF  outColor = mProfile->mFontColor ;
	   
	   if(mValue < mDamagedAmt)
	   {
		   outColor = mDamagedColor;
	   }
		
	   Point2I dropPos;
		
	   dropPos.x = offset.x + mDropOffset.x;
	   dropPos.y = offset.y + mDropOffset.y;


	   GFX->getDrawUtil()->setBitmapModulation(mDropColor);
	   GFX->getDrawUtil()->drawText(mProfile->mFont, dropPos, buf);
	   GFX->getDrawUtil()->clearBitmapModulation();

	   GFX->getDrawUtil()->setBitmapModulation( outColor );
	   GFX->getDrawUtil()->drawText(mProfile->mFont, offset, buf);
	   GFX->getDrawUtil()->clearBitmapModulation();

   }
	else //< pg health enhancement
   GFX->getDrawUtil()->drawRectFill(rect, mDamageFillColor);

The Next Gem
We will look at expanding the functionality of the stock Torque GuiShapeNameHud to show a player's health as well as the name.

#1
08/18/2008 (7:13 am)
oh, great... thanks for sharing. will try today
#2
08/18/2008 (12:37 pm)
Great resource! I've been wanting to add that to my project for a while, but hadn't gotten around to it. Thanks!! :)
#3
08/18/2008 (5:13 pm)
Anyone have pic of this ,is will be great ^^
#4
08/19/2008 (9:06 am)
I am getting the following error. I went through the above code and was wondering if it is because of AFX or something else. TGEA 1.7.1 with AFX. Also I have not been completeing the previous plastic gems would that also be a problem?

guiHealthBarHud.cpp
..\..\..\..\..\engine\source\T3D\fps\guiHealthBarHud.cpp(175) : error C2248: 'GuiControl::mBounds' : cannot access private member declared in class 'GuiControl'
        c:\Torque\AFX112_Combo_TGEA171_SDK\engine\source\gui/core/guiControl.h(84) : see declaration of 'GuiControl::mBounds'
        c:\Torque\AFX112_Combo_TGEA171_SDK\engine\source\gui/core/guiControl.h(77) : see declaration of 'GuiControl'
..\..\..\..\..\engine\source\T3D\fps\guiHealthBarHud.cpp(176) : error C2248: 'GuiControl::mBounds' : cannot access private member declared in class 'GuiControl'
        c:\Torque\AFX112_Combo_TGEA171_SDK\engine\source\gui/core/guiControl.h(84) : see declaration of 'GuiControl::mBounds'
        c:\Torque\AFX112_Combo_TGEA171_SDK\engine\source\gui/core/guiControl.h(77) : see declaration of 'GuiControl'
#5
08/19/2008 (9:59 am)
NVM I got it to work by moving mBounds from private to public. Thanks
#6
08/20/2008 (7:33 am)
Sound good...
#7
06/18/2009 (9:35 pm)
Quote:
I got it to work by moving mBounds from private to public.
Use getBounds() instead.
#8
02/18/2010 (10:58 pm)
nice, worked awesome