Game Development Community

dev|Pro Game Development Curriculum

Plastic Gem #42: Shape Name Hud Upgrades

by Anthony Rosenbaum · 08/19/2008 (6:24 am) · 8 comments

Download Code File


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



Shape Name Hud

Difficulty: Easy


In this article we are going to improve the GuiShapeNameHud so that it shows the players health along with their name. This code is actually pretty straight forward it is taken from GuiCrossHairHud and has been placed in the GuiShapeNameHud. As an addition we have exposed additional colors so that as the player's health depletes you will be able to see it as a color change on the bar. 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

1) Add these properties to the GuiShapeNameHud class definition


// > pg health enhancement
   ColorF   mDamageFillColor;
   ColorF   mGreenColor;
   ColorF   mLowHealthColor;
   ColorF   mDamageFrameColor;
   Point2I  mDamageRectSize;
   Point2I  mDamageOffset;
   F32      mUnhealthyPercent;
   F32      mYellowPercent;
   F32      mMinAlpha;
 // < pg health enhancement

We will also add a new method for rendering the name and damage

2) Also in GuiShapeNameHud class definition add to the protected section:


// > pg health enhancement
   void drawNameAndDamage( Point2I offset, const char *buf, F32 damage, F32 opacity);
    // < pg health enhancement

On to initializing the new properties

3) Within the constructor GuiShapeNameHud::GuiShapeNameHud() add:


// > pg health enhancement
   mDamageFillColor.set( 0, 1, 0, 1 );
   mLowHealthColor.set( 1, 0, 0, 1 );
   mDamageFrameColor.set( 1, 0.6, 0, 1 );
   mDamageRectSize.set(50, 4);
   mDamageOffset.set(0,32);
   mUnhealthyPercent = 0.3;
   mMinAlpha = 0.2;
   mYellowPercent = 0.6;
   mGreenColor.set(0, 1, 0, 1);
 // < pg health enhancement

Now to expose the properties to the editor ( are you learning how Torque works yet?)

4) At the bottom of GuiShapeNameHud::initPersistFields() add


// > pg health enhancement
   addGroup("Damage");		
   addField( "damageFillColor", TypeColorF, Offset( mDamageFillColor, GuiShapeNameHud ) );
   addField( "damageFrameColor", TypeColorF, Offset( mDamageFrameColor, GuiShapeNameHud ) );
   addField( "damageRect", TypePoint2I, Offset( mDamageRectSize, GuiShapeNameHud ) );
   addField( "damageOffset", TypePoint2I, Offset( mDamageOffset, GuiShapeNameHud ) );
   addField( "lowHealthColor", TypeColorF, Offset( mLowHealthColor, GuiShapeNameHud ) );
   addField( "unhealthyPercent",TypeF32, Offset (mUnhealthyPercent, GuiShapeNameHud));
   addField( "minAlpha", TypeF32, Offset( mMinAlpha, GuiShapeNameHud ) );
   addField( "yellowPercent", TypeF32, Offset( mYellowPercent, GuiShapeNameHud ) );
   addField( "greenColor", TypeColorF, Offset( mGreenColor, GuiShapeNameHud ) );
   endGroup("Damage"); 
    // < pg health enhancement

Now we are going to remove the old way of rendering the name for our new way of rendering the name and damage bar.

5) In GuiShapeNameHud::onRender() replace drawName() with this code


// > pg pg health enhancement
	if(opacity < mMinAlpha)
		opacity = mMinAlpha;
// Render the shape's name and damage
drawNameAndDamage(Point2I((S32)projPnt.x, (S32)projPnt.y), shape->getShapeName(), shape->getDamageValue(), opacity);
		      //< pg pg health enhancement


Now add our custom rending method

6) At the bottom of the file add this function


// > pg health enhancement
//----------------------------------------------------------------------------
/// Render object names.
///
/// Helper function for GuiShapeNameHud::onRender
///
/// @param   offset  Screen coordinates to render name label. (Text is centered
///                  horizontally about this location, with bottom of text at
///                  specified y position.)
/// @param   name    String name to display.
/// @param   damage  Damage to display
/// @param   opacity Opacity of name (a fraction).
void GuiShapeNameHud::drawNameAndDamage(Point2I offset, const char *name, F32 damage, F32 opacity)
{
   mDamageFillColor.alpha = mDamageFrameColor.alpha = opacity;

   // Damage should be 0->1 (0 being no damage,or healthy), but
   // we'll just make sure here as we flip it.
   damage = mClampF(1 - damage, 0, 1);
   ColorF outColor = mGreenColor;
	//full is green
   //turn to red if below 50

   if(damage <= mYellowPercent)
	   outColor = mDamageFillColor;

   if(damage <= mUnhealthyPercent)
		outColor = mLowHealthColor;


   // text info
   //StringBuffer sb;
   //sb.append(name);
   //S32 width = mProfile->mFont->getStrNWidth(sb.getPtr(),sb.length());
   S32 width = mProfile->mFont->getStrWidth(name);
   S32 height = mProfile->mFont->getHeight();

   // setup bar for rect...
   RectI rect(offset, mDamageRectSize);
   rect.point.y -= height;
   rect.point.x -= mDamageRectSize.x / 2;
   rect.point += mDamageOffset;

   // setup bar for name...
   RectI nameRect(offset, Point2I(width,height));
   nameRect.point.y -= height;
   // for now center on bar as width = fuckyup
   //nameRect.point.x -= width / 2;
   nameRect.point.x -= mDamageRectSize.x / 2;

   // draw name..
   mTextColor.alpha = opacity;
   dglSetBitmapModulation(mTextColor);
   dglDrawText(mProfile->mFont, nameRect.point, name);
   dglClearBitmapModulation();

   // (to help debug strWidth() stuff we can draw border around name too...
   //dglDrawRect(nameRect, mDamageFrameColor);

   // draw bar...

   // Draw the border
   //draw filled to get perspective
   dglDrawRectFill(rect, mDamageFrameColor);

   // Draw the damage % fill
   rect.point += Point2I(1, 1);
   rect.extent -= Point2I(1, 1);
   rect.extent.x = (S32)(rect.extent.x * damage);
   if (rect.extent.x == 1)
      rect.extent.x = 2;
   if (rect.extent.x > 0)
      dglDrawRectFill(rect, outColor);
}	
// < pg health enhancement


For TGEA simple rewrite the function to use the GFX interface

6) At the bottom of the file add this function


// > pg health enhancement
//----------------------------------------------------------------------------
/// Render object names.
///
/// Helper function for GuiShapeNameHud::onRender
///
/// @param   offset  Screen coordinates to render name label. (Text is centered
///                  horizontally about this location, with bottom of text at
///                  specified y position.)
/// @param   name    String name to display.
/// @param   damage  Damage to display
/// @param   opacity Opacity of name (a fraction).
void GuiShapeNameHud::drawNameAndDamage(Point2I offset, const char *name, F32 damage, F32 opacity)
{
   mDamageFillColor.alpha = mDamageFrameColor.alpha = opacity;

   // Damage should be 0->1 (0 being no damage,or healthy), but
   // we'll just make sure here as we flip it.
   damage = mClampF(1 - damage, 0, 1);
   ColorF outColor = mGreenColor;
   //turn to red if below 50
	//full is green
   //turn to red if below 50

   if(damage <= mYellowPercent)
	   outColor = mDamageFillColor;

   if(damage <= mUnhealthyPercent)
		outColor = mLowHealthColor;


   // text info
   //StringBuffer sb;
   //sb.append(name);
   //S32 width = mProfile->mFont->getStrNWidth(sb.getPtr(),sb.length());
   S32 width = mProfile->mFont->getStrWidth(name);
   S32 height = mProfile->mFont->getHeight();

   // setup bar for rect...
   RectI rect(offset, mDamageRectSize);
   rect.point.y -= height;
   rect.point.x -= mDamageRectSize.x / 2;
   rect.point += mDamageOffset;

   // setup bar for name...
   RectI nameRect(offset, Point2I(width,height));
   nameRect.point.y -= height;
   // for now center on bar as width = fuckyup
   //nameRect.point.x -= width / 2;
   nameRect.point.x -= mDamageRectSize.x / 2;

   // draw name..
   mTextColor.alpha = opacity;

	GFX->getDrawUtil()->drawRect(rect, mDamageFrameColor);
   // Draw the damage % fill
   rect.point += Point2I(1, 1);
   rect.extent -= Point2I(1, 1);
   rect.extent.x = (S32)(rect.extent.x * damage);
   if (rect.extent.x == 1)
      rect.extent.x = 2;
   if (rect.extent.x > 0)
    GFX->getDrawUtil()->drawRectFill(rect, outColor);
}
// < pg health enhancement

There you have it, not only it is a nice improvement this article give you something to compare against incase you are porting some custom GUIs from TGE to TGEA.

The Next Gem
We will look at fixing the Camera Object orbit position feature.

#1
08/20/2008 (7:35 am)
Coooool...
#2
08/22/2008 (8:01 pm)
Most useful.Thx.
#3
09/09/2008 (5:40 am)
Hi, i have a question related to nameHud.

the code guiShapeNameHud.cc commented on line 188 that:
// and we want to ignore anything it's mounted on when we run the LOS.

does it mean that it will still show up the name when i mount some static object onto the shape base player? But it doesn't work in that way, the text disappear after mounting.

Do you have any suggestions about how to fix it?

Thanks so much.
#4
01/07/2009 (7:47 am)
Nancy - sorry for late reply. Did you get past this issue yet? I guess if you mount something to the shapebase player you need to ensure that mounted thing ALSO does not block LOS. Perhaps you need to disable collision on that mounted shape for this test?
#5
03/09/2009 (5:13 am)
Does this work in TGEA 1.8.1?
#6
02/18/2010 (11:02 pm)
Worked great in my 1.8.2 project
#7
03/01/2012 (2:05 pm)
Thanks! This drops right into T3D v1.2, with no changes required! just used the above TGE code, plus the TGEA render code.
#8
03/17/2012 (6:35 pm)
The link to the download code is broken, does anyone happen to still have the dl available?