.. _doc_your_first_2d_game_heads_up_display: 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 :ref:`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 :ref:`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 :ref:`Control `. To create our UI, we'll use two types of :ref:`Control ` nodes: :ref:`Label ` and :ref:`Button `. Create the following as children of the ``HUD`` node: - :ref:`Label ` named ``ScoreLabel``. - :ref:`Label ` named ``Message``. - :ref:`Button ` named ``StartButton``. - :ref:`Timer ` named ``MessageTimer``. 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** click on the empty box and select "New DynamicFont" .. image:: img/custom_font1.png 2. Click on the "DynamicFont" you added, and under **Font > FontData**, choose "Load" and select the "Xolonium-Regular.ttf" file. .. image:: img/custom_font2.png Set the "Size" property under ``Settings``, ``64`` works well. .. image:: img/custom_font3.png 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. .. note:: **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: .. image:: img/ui_anchor.png You can drag the nodes to place them manually, or for more precise placement, use the following settings: ScoreLabel ~~~~~~~~~~ - *Layout* : "Top Wide" - *Text* : ``0`` - *Align* : "Center" Message ~~~~~~~~~~~~ - *Layout* : "HCenter Wide" - *Text* : ``Dodge the Creeps!`` - *Align* : "Center" - *Autowrap* : "On" StartButton ~~~~~~~~~~~ - *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``: .. tabs:: .. code-tab:: gdscript GDScript extends CanvasLayer signal start_game .. code-tab:: csharp public class HUD : CanvasLayer { // Don't forget to rebuild the project so the editor knows about the new signal. [Signal] public delegate void StartGame(); } .. code-tab:: cpp // Copy `player.gdns` to `hud.gdns` and replace `Player` with `HUD`. // Attach the `hud.gdns` file to the HUD node. // Create two files `hud.cpp` and `hud.hpp` next to `entry.cpp` in `src`. // This code goes in `hud.hpp`. We also define the methods we'll be using here. #ifndef HUD_H #define HUD_H #include #include #include #include #include class HUD : public godot::CanvasLayer { GODOT_CLASS(HUD, godot::CanvasLayer) godot::Label *_score_label; godot::Label *_message_label; godot::Timer *_start_message_timer; godot::Timer *_get_ready_message_timer; godot::Button *_start_button; godot::Timer *_start_button_timer; public: void _init() {} void _ready(); void show_get_ready(); void show_game_over(); void update_score(const int score); void _on_StartButton_pressed(); void _on_StartMessageTimer_timeout(); void _on_GetReadyMessageTimer_timeout(); static void _register_methods(); }; #endif // HUD_H The ``start_game`` signal tells the ``Main`` node that the button has been pressed. .. tabs:: .. code-tab:: gdscript GDScript func show_message(text): $Message.text = text $Message.show() $MessageTimer.start() .. code-tab:: csharp public void ShowMessage(string text) { var message = GetNode