Heads up display

The final piece our game needs is a User Interface (UI) to display things like score, a "game over" message, and a restart button.

Create a new scene, and add a CanvasLayer node named HUD. "HUD" stands for "heads-up display", an informational display that appears as an overlay on top of the game view.

The CanvasLayer node lets us draw our UI elements on a layer above the rest of the game, so that the information it displays isn't covered up by any game elements like the player or mobs.

The HUD needs to display the following information:

  • Score, changed by ScoreTimer.

  • A message, such as "Game Over" or "Get Ready!"

  • A "Start" button to begin the game.

The basic node for UI elements is Control. To create our UI, we'll use two types of Control nodes: Label and Button.

Create the following as children of the HUD node:

Click on the ScoreLabel and type a number into the Text field in the Inspector. The default font for Control nodes is small and doesn't scale well. There is a font file included in the game assets called "Xolonium-Regular.ttf". To use this font, do the following:

  1. Under "Theme Overrides > Fonts", choose "New Font".

  1. Click on the "Font" you added, and under "Font/Data/0", choose "Load" and select the "Xolonium-Regular.ttf" file.


Once you've done this on the ScoreLabel, you can click the down arrow next to the Font property and choose "Copy", then "Paste" it in the same place on the other two Control nodes. Set the "Font Size" property of the ScoreLabel under "Theme Overrides > Font Sizes". A setting of 64 works well.



Anchors and Margins: Control nodes have a position and size, but they also have anchors and margins. Anchors define the origin - the reference point for the edges of the node. Margins update automatically when you move or resize a control node. They represent the distance from the control node's edges to its anchor.

Arrange the nodes as shown below. Click the "Layout" button to set a Control node's layout:


You can drag the nodes to place them manually, or for more precise placement, use the following settings:


  • Layout : "Top Wide"

  • Text : 0

  • Alignment : "Center"


  • Layout : "HCenter Wide"

  • Text : Dodge the Creeps!

  • Alignment : "Center"

  • Autowrap : "On"


  • Text : Start

  • Layout : "Center Bottom"

  • Margin :

    • Top: -200

    • Bottom: -100

On the MessageTimer, set the Wait Time to 2 and set the One Shot property to "On".

Now add this script to HUD:

extends CanvasLayer

# Notifies `Main` node that the button has been pressed
signal start_game

We now want to display a message temporarily, such as "Get Ready", so we add the following code

func show_message(text):
    $Message.text = text

We also need to process what happens when the player loses. The code below will show "Game Over" for 2 seconds, then return to the title screen and, after a brief pause, show the "Start" button.

func show_game_over():
    show_message("Game Over")
    # Wait until the MessageTimer has counted down.
    await $MessageTimer.timeout

    $Message.text = "Dodge the\nCreeps!"
    # Make a one-shot timer and wait fo