Displaying messages on the HUD
Inside the
Inside the AMyHUD AMyHUD class, we need to implement the class, we need to implement theDrawHUD()DrawHUD() function in order to function in order to draw our messages to the HUD and to initialize a font to draw to the
draw our messages to the HUD and to initialize a font to draw to the HUD with,HUD with, as shown in the
as shown in the following code:following code:
UCLASS() UCLASS()
class GOLDENEGG_API AMyHUD : public AHUD class GOLDENEGG_API AMyHUD : public AHUD {
{
GENERATED_UCLASS_BODY() GENERATED_UCLASS_BODY()
// The
// The font used font used to render to render the text the text in the HUin the HUD.D. UPROPERTY(EditAnywhere,
UPROPERTY(EditAnywhere, BlueprintReadWrite, BlueprintReadWrite, Category Category = = HUDFont)HUDFont) UFont*
UFont* hudFont;hudFont; // Add
The HUD font will be set in a
The HUD font will be set in a blueprinted version of theblueprinted version of the AMyHUD AMyHUD class. The class. The
DrawHUD()
DrawHUD() function runs once per frame. In order to draw within the frame, function runs once per frame. In order to draw within the frame, add a function to the
add a function to the AMyHUD.cpp AMyHUD.cppfifile:le:
void AMyHUD::DrawHUD() void AMyHUD::DrawHUD() {
{ //
// call call superclass superclass DrawHUD() DrawHUD() function function firstfirst Super::DrawHUD();
Super::DrawHUD(); // the
// then proceed n proceed to draw to draw your syour stuff.tuff. //
// we we can can draw draw lines..lines.. DrawLine(
DrawLine( 200, 3200, 300, 400, 00, 400, 500, FLine500, FLinearColor::Blue arColor::Blue );); //
// and and we cwe can dran draw teaw text!xt! DrawText( "
DrawText( "Greetings from Greetings from Unreal!", FVecUnreal!", FVector2D( 0, tor2D( 0, 0 ), 0 ), hudFont,hudFont, FVector2D( 1, 1 ), FColor::White );
FVector2D( 1, 1 ), FColor::White ); }
}
Wait! We haven't initialized our font yet. To do this, we need to set
Wait! We haven't initialized our font yet. To do this, we need to set it up init up in blueprints. Compile and run your Visual Studio project. Once you
blueprints. Compile and run your Visual Studio project. Once you are in the are in the editor,editor, go to the
go to the BlueprintsBlueprints menu at the top and menu at the top and navigate tonavigate to GameModeGameMode|| HUD HUD|| + Create + Create |
| MyHUD MyHUD..
Creating a blueprint of the MyHUD class Creating a blueprint of the MyHUD class
I called mine
I called mineBP_MyHUDBP_MyHUD. Edit. EditBP_MyHUDBP_MyHUD and select a font from the drop-down menu and select a font from the drop-down menu under
under HUDFontHUDFont::
I selected RobotoDistanceField for my HUD font I selected RobotoDistanceField for my HUD font
Next, edit your
Next, edit your Game ModeGame Mode blueprint ( blueprint (BP_GameModeGoldenEgg BP_GameModeGoldenEgg ) and select your) and select your new
Test your program by running it! You should see text printed on the screen. Test your program by running it! You should see text printed on the screen.
Using TArray<Message>
Using TArray<Message>
Each message we want to display for the player will have a few properties: Each message we want to display for the player will have a few properties:
• An
• AnFStringFString variable for the message variable for the message •
• AAfloatfloat variable for the time to display it variable for the time to display it • An
• An FColorFColor variable for the color of the message variable for the color of the message So it makes sense for us to write a
So it makes sense for us to write a littlelittlestructstruct function to function to contain allcontain all this information.
this information. At the top of
At the top of MyHUD.hMyHUD.h, insert the following, insert the followingstructstruct declaration: declaration:
struct Message struct Message {
{
FString
FString message;message; float
float time;time; FColor
FColor color;color; Message() Message()
{ {
//
// Set Set the the default default time.time. time
time = = 5.f;5.f; color
color = = FColor::White;FColor::White; }
}
Message( FS
message
message = = iMessage;iMessage; time
time = = iTime;iTime; color
color = = iColor;iColor; }
} }; };
An enhanced version of the
An enhanced version of the MessageMessage structure (with a background structure (with a background color) is in the code package for this chapter. We used simpler code color) is in the code package for this chapter. We used simpler code here so that it'd be easier to
here so that it'd be easier to understand the chapter.understand the chapter.
Now, inside the
Now, inside the AMyHUD AMyHUD class, we want to add a class, we want to add a TArrayTArray of these messages. A of these messages. ATArrayTArray
is a UE4-de
is a UE4-defifined special type of dynamically growable C++ array. We ned special type of dynamically growable C++ array. We will cover thewill cover the
detailed use of
detailed use of TArrayTArray in the next chapter, but this in the next chapter, but this simple usage ofsimple usage of TArrayTArray should should be a nice introduction to garner your interest in the usefulness of arrays in games. be a nice introduction to garner your interest in the usefulness of arrays in games. This will be declared as
This will be declared as TArray<Message>TArray<Message>::
UCLASS() UCLASS()
class GOLDENEGG_API AMyHUD : public AHUD class GOLDENEGG_API AMyHUD : public AHUD {
{
GENERATED_UCLASS_BODY() GENERATED_UCLASS_BODY()
// The
// The font used font used to render to render the text the text in the HUin the HUD.D. UPROPERTY(EditAnywhere,
UPROPERTY(EditAnywhere, BlueprintReadWrite, BlueprintReadWrite, Category Category = = HUDFont)HUDFont) UFont*
UFont* hudFont;hudFont; // New
// New! An ! An array of array of messages messages for difor displaysplay TArray<Message>
TArray<Message> messages;messages; virtual
virtual void void DrawHUD() DrawHUD() override;override; // New!
// New! A function A function to be to be able to adable to add a messagd a message to dispe to displaylay void
void addMessage( addMessage( Message Message msg msg );); };
};
Now, whenever the NPC has a message to display, we're just need to Now, whenever the NPC has a message to display, we're just need to callcall
AMyHud::addMessage()
AMyHud::addMessage() with our message. The message will be added to with our message. The message will be added to TArrayTArray
of the messages to be displayed. When a message expires (after a certain amount of of the messages to be displayed. When a message expires (after a certain amount of time), it will be removed from the HUD.
time), it will be removed from the HUD. Inside the
Inside the AMyHUD.cpp AMyHUD.cppfifile, add the following code:le, add the following code:
void AMyHUD::DrawHUD() void AMyHUD::DrawHUD() { { Super::DrawHUD(); Super::DrawHUD(); // iterate
// iterate from back from back to front to front thru the lthru the list, so if ist, so if we removewe remove // an
// an item while item while iterating, there iterating, there won't be won't be any problemsany problems for( int
//
// for for the the messagemessage float
float outputWidth, outputWidth, outputHeight, outputHeight, pad=10.f;pad=10.f; GetTextSize(
GetTextSize( messages[c].message, messages[c].message, outputWidth, outputWidth, outputHeight,outputHeight, hudFont, 1.f );
hudFont, 1.f ); float
float messageH messageH = = outputHeight outputHeight + + 2.f*pad;2.f*pad; float
float x x = = 0.f, 0.f, y y = = c*messageH;c*messageH; //
// black black backingbacking DrawRect(
DrawRect( FLinearColor::Black, FLinearColor::Black, x, x, y, y, Canvas->SizeX, Canvas->SizeX, messageHmessageH );
); //
// draw draw our our message message using using the the hudFonthudFont DrawText(
DrawText( messages[c].message, messages[c].message, messages[c].color, messages[c].color, x x + + pad, pad, y y ++ pad, hudFont );
pad, hudFont ); //
// reduce reduce lifetime lifetime by by the the time time that that passed passed since since lastlast // frame.
// frame.
messages[c].time
messages[c].time -= -= GetWorld()->GetDeltaSeconds(GetWorld()->GetDeltaSeconds();); //
// if if the the message's message's time time is is up, up, remove remove itit if(
if( messages[c].time messages[c].time < < 0 0 )) { { messages.RemoveAt( messages.RemoveAt( c c );); } } } } } }
void AMyHUD::addMessage( Message msg ) void AMyHUD::addMessage( Message msg ) { { messages.Add( messages.Add( msg msg );); } } The
The AMyHUD::DrawHUD() AMyHUD::DrawHUD() function now draws all the messages in the function now draws all the messages in themessagesmessages
array, and arranges each message in the
array, and arranges each message in themessagesmessages array by the amount of time array by the amount of time that passed since the last frame. Expired messages are removed from the
that passed since the last frame. Expired messages are removed from themessagesmessages
collection once their
collection once their timetime value drops below 0. value drops below 0.
Exercise
Exercise
Refactor the
Refactor theDrawHUD()DrawHUD() function so that the code that draws the function so that the code that draws the messages to themessages to the screen is in a separate function called
screen is in a separate function called DrawMessages()DrawMessages().. The
Refactoring means to change the way code
Refactoring means to change the way code works internally so that it iworks internally so that it iss more organized or easier to read but
more organized or easier to read but still has the same apparent result tostill has the same apparent result to the user running the program. Refactoring often i
the user running the program. Refactoring often is a good practice. Thes a good practice. The reason why refactoring occurs is because nobody
reason why refactoring occurs is because nobody knows exactly whatknows exactly what the
thefifinal code should look like once they start writing it.nal code should look like once they start writing it.
Solution
Solution
See the
See the AMyHUD::DrawMessages() AMyHUD::DrawMessages() function in the code package for this chapter. function in the code package for this chapter.