Drawing Vertical HUD Bars

From Oldunreal-Wiki
Jump to navigation Jump to search

Someone asked how to do this in the Coding area of the BeyondUnreal forums, and I decided that it might be nice to have a tutorial on this subject. If you're that person, I took the liberty of changing your idea a bit, but you should be able to understand what to do. I assume that you already have UClasses (or some other way to compile your code outside of UnrealEd) up and running. You won't be able to follow this tutorial precisely if you don't use "UCC -make" to compile your code, as you'll be importing some graphics as well. (If you're not sure what UCC is, it generally means you're not using UnrealEd) I also assume that you have a basic understanding of the C++ like syntax unrealscript uses.

What I'll be explaining here is how to remove the status doll and health+armour readouts in the top left corner of the screen, and how to replace them with two neat, easily readable bars. We'll be subclassing the ChallengeHUD for this, so we'll need to make a new game-type to show the new HUD.

If you have it, you should fire up UClasses, and make a class below ChallengeHUD. To do this, you should expand Actor, then HUD, then right-click on ChallengeHUD and below "Add edit remove", choose "Create new class below ChallengeHUD". In Classname, fill in something like "HUDwithHPbars" or something. Come up with a name. : ) You should also make up a name for your package, just call it "BarsTutorial" (the name I'll refer to in this tutorial from no on) or whatever, as long as the name doesn't already exist. Well, there's your new HUD class. Double click on it to open it up in a text-editor.

It doesn't have any code in there, so right now it'd act just like a normal HUD.

If you made this class without UClasses, you should make it look like this:

class HUDwithHPbars expands ChallengeHUD;
defaultproperties
{
}


Luckily, our HUDs parent class, ChallengeHUD, is very organized, so all the code that draws the players status in the top-left corner is contained in one function. By overriding that function in our new class, we'll make sure it isn't drawn. So, between the class defenition ( class X expands Y; ) and the default properties, you should put

simulated function DrawStatus(Canvas Canvas)
{
}

Luckily, our HUDs parent class, ChallengeHUD, is very organized, so all the code that draws the players status in the top-left corner is contained in one function. By overriding that function in our new class, we'll make sure it isn't drawn. So, between the class defenition ( class X expands Y; ) and the default properties, you should put

simulated function DrawStatus(Canvas Canvas) { }

Now, our new HUD has his own DrawStatus function, so it won't be using it's parent's. Before we go and start drawing the bars in the place of the status doll, we'll need to import the graphics for the bar. To import something, you have to use an "exec" command. Ours will look like this:

  1. exec TEXTURE IMPORT NAME=TwoBars FILE=Textures\Bars.pcx MIPS=OFF

This will tell the compiler to add Bars.pcx (located in our packages directory, in a subdirectoty called "Textures") to our new package. If you want to find out more about exec commands, there's a good document about them in the tutorials section of www.Unrealscript.com, the site this tutorial is probably situated as well. Now you'll probably want to download the Bars.pcx I made. If you decide to remake it yourself, put everything in the same place as in the original, because this tutorial counts on it. After you've downloaded Bars.pcx, and maybe remade it, find the directory with the same name as your package in the Unreal Tournament directory. It should already have a subdirectory "Classes", now make another directory there named "Textures" and put the .pcx in there.

Now, we'll need to put the code up there that will display the bars on-screen. We'll just put our code in the DrawStatus function, since we're sure it's called and it's unused now anyway. We'll first draw the holders, like so:

simulated function DrawStatus(Canvas Canvas)
{
 if ( !bHideStatus ) // we wouldn't want our bars to show up if the player doesn't want them
 {
   Canvas.Style = ERenderStyle.STY_Normal; // So you won't be able to see through the bars
   Canvas.SetPos(Canvas.ClipX - 32, 0); // The first thing to do is setting drawing offset at the right place,
   // and since the placeholder graphic is 32 pixels wide, we want it to be 32 pixels from the right side of the screen (ClipX)
   Canvas.DrawTile(Texture'BarsTutorial.TwoBars', 32, 144, 32, 0, 32.0, 144.0);
   Canvas.SetPos(Canvas.ClipX - 64, 0); // 32 pixels more to the right.
   Canvas.DrawTile(Texture'BarsTutorial.TwoBars', 32, 144, 32, 0, 32.0, 144.0);
 }
}

This is what it's all about. Drawtile is what you use most of the time to put things on the HUD.

The first argument reads Texture'Tutorial.TwoBars'. This is the texture we're using, and the one exec'll import. The second and third are 32,144. These are the dimensions the tile will be on the screen. The fourth and fifth are 32,0. This is the top left corner of the tile in the used texture (here: TwoBars, which is the name we gave to Bars.pcx). The sixth and seventh are the dimensions of the tile in the graphic. Just for ease, the second and third are the same as this, but if they were different, the graphic would be resized on the fly.

Now, we'd want to test out this HUD, but we'll need to create a new gametype for that. Just subclass DeathMatchPlus, name it DeathMatchPlusBars and have it look like this:

class DeathMatchPlusBars expands DeathMatchPlus;
defaultproperties
{
    HUDType=Class'BarsTutorial.HUDwithHPbars' // this is the HUD we've made!
    GameName="Just a HUD test"
}

This should pretty much work when you compile it. Put the .int file that came with the .pcx file in your system directory, modify it to match your package name, compile your package with UClasses and try it out! (select the "Just a HUD test" from the games list) The bars' placeholders should show up, but the actual bars are nowhere to be seen yet. Adding them is easy, and is quite the same procedure as drawing the placeholders. Below is all the code your class should contain. (Including the class defenition and the importing #exec function)

class HUDwithHPbars expands ChallengeHUD;

#exec TEXTURE IMPORT NAME=TwoBars FILE=Textures\Bars.pcx MIPS=OFF
simulated function DrawStatus(Canvas Canvas)
{
 local TournamentPlayer POwner;
 local int ArmorAmount,CurAbs,i;
 local inventory Inv,BestArmor;
 POwner = TournamentPlayer(Owner); // We need to make sure we're dealing with a player here, because not all Owners have health
 // The following code (until !bhidestatus) was copied from ChallengeHUD, and figures out how much armour the player has
 // It isn't complicated at all, but it isn't really important for this tutorial.
 for( Inv=POwner.Inventory; Inv!=None; Inv=Inv.Inventory )
 {
   if (Inv.bIsAnArmor)
   {
     ArmorAmount += Inv.Charge;
   }
   else
   {
     i++;
     if ( i > 100 )
       break; // can occasionally get temporary loops in netplay
   }
 }
 if ( !bHideStatus ) // we wouldn't want our bars to show up if the player doesn't want them
 {
   Canvas.Style = ERenderStyle.STY_Normal; // So you won't be able to see through the bars
   Canvas.SetPos(Canvas.ClipX - 32, 0); // The first thing to do is setting drawing offset at the right place,
   // and since the placeholder graphic is 32 pixels wide, we want it to be 32 pixels from the right side of the screen (ClipX)
   Canvas.DrawTile(Texture'BarsTutorial.TwoBars', 32, 144, 32, 0, 32.0, 144.0);
   Canvas.SetPos(Canvas.ClipX - 64, 0); // 32 pixels more to the right.
   Canvas.DrawTile(Texture'BarsTutorial.TwoBars', 32, 144, 32, 0, 32.0, 144.0);
   // Let's add the bars themselves now.
   Canvas.SetPos(Canvas.ClipX - 32 + 16, 8); // We want the bars to show up 16 pixels to the right and 8 pixels down on the
   // placeholders
   Canvas.DrawTile(Texture'BarsTutorial.TwoBars', 8, 128*POwner.Health/200, 16, 0, 16.0, 128.0);
   Canvas.SetPos(Canvas.ClipX - 64 + 16, 8);
   Canvas.DrawTile(Texture'BarsTutorial.TwoBars', 8, 128*ArmorAmount/150, 0, 0, 16.0, 128.0);
 }
}
defaultproperties
{
}

With everything I told you, you should be able to understand everything of the above. You should expiriment a bit with the code, try to make the bars start at the bottom of the placeholder for example. If you feel confident, you could even try to scale the bars up a bit, according to the resolution, keeping in mind that the resolution is kept in Canvas.ClipX and Canvas.ClipY, that the second and third arguments of Canvas.DrawTile are the size of the tile on-screen and that the bars look good already on low resolutions. Checking out the code of the original ChallengeHUD's DrawStatus function should give you enough information to allow the player to resize the bars, and there are bound to be more ways to improve the code above.

If you have suggestions or find a bad error in this tutorial, you can mail me at Bokkelstra@Hotmail.com (Yes, I know it's a weird E-mail adress, I just registered it in order to keep stuff apart) This .zip file contains the texture & .int file necessary to use the example code in the tutorial.

G'luck on your further coding, and farewell! -The Apeman