Friday, May 25, 2012

Platformer Kit: SPG_HUD class (UnrealScript)

We have seen several concepts related to programming with UnrealScript. Now it's time to see all these concepts together and applied in a game.

In UDN (Unreal Developer Network) there is an excellent game example to study UnrealScript which is the Platformer Starter Kit, available at:

This page at UDN has all the necessary guidelines to configure and run the Kit in UDK.

The UnrealScript source code of the Platformer Starter Kit is very well commented. Even so, some parts of the code is very complex for Beginners in UnrealScript. I'll start a series of articles analyzing the existing UnrealScript classes in the Platformer Starter Kit with the goal of generating an additional material to help in understanding the logic of this example of a functional game.

Let's start by looking at the simplest class: SPG_HUD. The only goal of this class is to draw on the bottom left of the screen the text "Health" with the numeric value that represents the current health of the player as in the image below.


If you do not know anything about the HUD class, I recommend reading my article "Drawing the HUD".

The SPG_HUD class has only the PostRender() function containing the following code.
event PostRender()
{
    local float XL, YL;
    local String Text;

    Super.PostRender();

    // Ensure that PlayerOwner and PlayerOwner.Pawn are valid
    if (PlayerOwner != None && PlayerOwner.Pawn != None)
    {
        // Set the text to say Health: and the numerical value of the player pawn's health
        Text = "Health: " $ PlayerOwner.Pawn.Health;
        // Set the font
        Canvas.Font = class'Engine'.static.GetMediumFont();
        // Set the current drawing color
        Canvas.SetDrawColor(255, 255, 255);
        // Get the dimensions of the text in the font assigned
        Canvas.StrLen(Text, XL, YL);
        // Set the current drawing position to the be at the bottom left position with a padding of 4 pixels
        Canvas.SetPos(4, Canvas.ClipY - YL - 4);
        // Draw the text onto the screen
        Canvas.DrawText(Text);
    }
}

The comments below are related to existing concepts in the above code.

There are two main functions in the HUD class used to draw on the screen, which are "DrawHud()" and "PostRender()". The "DrawHud()" is only called if the variable bShowHud is equal to true and if the Score Table is not visible (bShowScores equal to false). To understand the relationship between the functions "DrawHud()" and "PostRender()", analyze the function "PostRender()" of the HUD class (Engine package).

The PlayerOwner variable is declared in the HUD class and represents the PlayerController responsible for the HUD. Its initialization is done in the function "PostBeginPlay()" of the HUD class.

The concatenation of strings can be done using two operators: $ and @. The only difference between them is that the @ operator puts a space between the strings. Numerical values ​​used in the concatenation are automatically converted to strings. Another way to concatenate strings is using the operators $= and @= that appends a string to an existing string variable. For example, to complement the text of the HUD with the information HealthMax, we can do so:
Text = "Health: " $ PlayerOwner.Pawn.Health;
Text @= "- HealthMax:" @ PlayerOwner.Pawn.HealthMax;

The font used to write the text is obtained from a static function in the Engine class. There are four pre-defined sizes of fonts that are obtained through the functions:
native static final function Font GetTinyFont();
native static final function Font GetSmallFont();
native static final function Font GetMediumFont();
native static final function Font GetLargeFont();

The definition of the font color is done by the SetDrawColor() function of the Canvas class. The color is represented in RGB format, where each parameter is one byte (0-255). It can also be defined the Alpha element of the color that represents its opacity. There is also the SetDrawColorStruct() function which receives a struct of type color. Below are the two functions:
native final function SetDrawColor(byte R, byte G, byte B, optional byte A = 255);

/** Set the draw color using a color struct */
final function SetDrawColorStruct(color C)
{
    SetDrawColor(C.R, C.G, C.B, C.A);
}