Heads up display (HUD)

La dernière pièce dont notre jeu a besoin est une Interface Utilisateur (IU), User Interface (UI) en anglais, pour afficher des éléments comme le score, un message "game over" et un bouton de redémarrage.

Créez une nouvelle scène, et ajoutez un nœud CanvasLayer nommé HUD. "HUD" signifie "heads-up display" un affichage informatif qui apparaît en surimpression sur la vue du jeu.

Le nœud CanvasLayer nous permet de dessiner nos éléments de l'interface utilisateur sur un calque au-dessus du reste du jeu, de sorte que les informations qu'il affiche ne sont couvertes par aucun élément du jeu comme le joueur ou les monstres.

Le HUD doit afficher les informations suivantes :

  • Le score, modifié par ScoreTimer.

  • Un message, tel que "Game Over" ou "Get Ready"

  • Un bouton "Démarrer" pour commencer le jeu.

Le nœud de base pour les éléments de l'interface utilisateur est Control. Pour créer notre interface utilisateur, nous utiliserons deux types de nœuds Control : Label et Button.

Créez les éléments suivants en tant qu'enfants du nœud HUD :

  • Un Label nommé ScoreLabel.

  • Un Label nommé Message.

  • Un Button nommé StartButton.

  • Un Timer nommé MessageTimer.

Cliquez sur le ScoreLabel et dans l'inspecteur, entrez un nombre dans le champ Text. La police par défaut pour les nœuds Control est petite et ne s'ajuste pas correctement. Il existe un fichier de police inclus dans les ressources du jeu appelé "Xolonium-Regular.ttf". Pour utiliser cette police, procédez comme suit :

  1. Sous Theme overrides > Fonts cliquez sur la case vide et sélectionnez "New DynamicFont"

../../_images/custom_font1.png
  1. Cliquez sur la "DynamicFont" que vous avez ajoutée, et sous Font > FontData, choisissez "Load" et sélectionnez le fichier "Xolonium-Regular.ttf".

../../_images/custom_font2.png

Définir la propriété "Size" sous Settings, 64 fonctionne bien.

../../_images/custom_font3.png

Une fois que vous avez fait cela sur le ScoreLabel, vous pouvez cliquer sur la flèche vers le bas à côté de la propriété Font et choisir "Copier", puis "Coller" au même endroit sur les deux autres nœuds Control.

Note

Ancres et marges : Les nœuds Control ont une position et une taille, mais ils ont aussi des ancres et des marges. Les ancres définissent l'origine - le point de référence pour les bords du nœud. Les marges se mettent à jour automatiquement lorsque vous déplacez ou redimensionnez un nœud control. Ils représentent la distance entre les bords du nœud control et son ancrage.

Disposez les nœuds comme indiqué ci-dessous. Cliquez sur le bouton "Layout" pour définir la disposition d'un nœud de contrôle :

../../_images/ui_anchor.png

Vous pouvez faire glisser les nœuds pour les placer manuellement ou, pour un placement plus précis, utiliser les paramètres suivants :

ScoreLabel

  • Layout / Disposition sur l'écran : "Top Wide"

  • Text : 0

  • Align : "Center"

Message

  • Layout / Disposition sur l'écran : "HCenter Wide"

  • Text : Dodge the Creeps!

  • Align : "Center"

  • Autowrap : "On"

StartButton

  • Text : Start

  • Layout / Disposition sur l'écran : "Center Bottom"

  • Margin :

    • Top : -200

    • Bottom : -100

Sur le MessageTimer, mettez le Wait Time à 2 et mettez la propriété One Shot à "On".

Ajoutez à présent ce script au HUD :

extends CanvasLayer

signal start_game

Le signal start_game indique au nœud Main que le bouton a été pressé.

func show_message(text):
    $Message.text = text
    $Message.show()
    $MessageTimer.start()

Cette fonction est appelée lorsque nous voulons afficher temporairement un message, tel que "Get Ready".

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

    $Message.text = "Dodge the\nCreeps!"
    $Message.show()
    # Make a one-shot timer and wait for it to finish.
    yield(get_tree().create_timer(1), "timeout")
    $StartButton.show()

Cette fonction est appelée lorsque le joueur perd. Elle affichera "Game Over" pendant 2 secondes, puis reviendra à l'écran de titre et affichera le bouton "Start".

Note

Quand vous avez besoin d'une courte pause, une alternative à l'utilisation d'un nœud Timer est d'utiliser la fonction create_timer() de l'arborescence de scène. Ceci peut être très utile pour créer un délais, comme dans le code ci-dessus, où nous voulons attendre un peu avant de faire apparaître le bouton "Start".

func update_score(score):
    $ScoreLabel.text = str(score)

Cette fonction est appelée dans Main chaque fois que le score change.

Connectez le signal timeout() de MessageTimer et le signal pressed() de StartButton et ajoutez le code suivant aux nouvelles fonctions :

func _on_StartButton_pressed():
    $StartButton.hide()
    emit_signal("start_game")

func _on_MessageTimer_timeout():
    $Message.hide()

Connecter le HUD à Main

Maintenant que nous avons fini de créer la scène du HUD, sauvegardez-la et retournez à Main. Instanciez la scène HUD dans Main comme vous l'avez fait dans la scène Player. L'arbre de scène devrait ressembler à ça, alors assurez-vous de ne rien manquer :

../../_images/completed_main_scene.png

Nous devons maintenant connecter la fonctionnalité HUD à notre script Main. Cela nécessite quelques ajouts à la scène Main :

Dans l'onglet Nœud, connectez le signal start_game du HUD à la fonction new_game() du nœud Main en tapant "new_game" dans la "Receiver Method" de la fenêtre "Connect a Signal". Vérifiez que l'icône de connexion verte apparaît maintenant à côté de func new_game() dans le script.

Dans new_game(), mettez à jour l'affichage des scores et affichez le message "Get Ready" :

$HUD.update_score(score)
$HUD.show_message("Get Ready")

Dans game_over() nous devons appeler la fonction HUD correspondante :

$HUD.show_game_over()

Enfin, ajoutez ceci à on_ScoreTimer_timeout() pour que l'affichage reste synchronisé avec le changement de score :

$HUD.update_score(score)

Vous êtes maintenant prêt à jouer ! Cliquez sur le bouton "Lancer le projet". Il vous sera demandé de sélectionner une scène principale, choisissez alors Main.tscn.

Supprimer les vieux Creeps

Si vous jouez jusqu'au "Game Over" et que vous commencez une nouvelle partie immédiatement, les monstres de la partie précédente sont toujours à l'écran. Il vaudrait mieux qu'ils disparaissent tous au début d'une nouvelle partie. Il nous faut juste un moyen de dire à tous les monstres de se supprimer. Nous pouvons le faire grâce à la fonction "groupe".

Dans la scène Mob, sélectionnez le nœud racine et cliquez sur l'onglet "Nœud" à côté de l'inspecteur (le même endroit où vous trouvez les signaux du nœud). À côté de "Signaux", cliquez sur "Groupes" et vous pouvez taper un nouveau nom de groupe et cliquer sur "Ajouter".

../../_images/group_tab.png

Maintenant, tous les mobs seront dans le groupe "mobs". Nous pouvons ensuite ajouter la ligne suivante à la fonction new_game() dans Main :

get_tree().call_group("mobs", "queue_free")

La fonction call_group() appelle la fonction nommée sur chaque nœud d'un groupe - dans ce cas nous disons à chaque mob de s'effacer eux-même.

Le jeu est pratiquement terminé à ce stade. Dans la prochaine et dernière partie, nous allons le peaufiner un peu en ajoutant un arrière-plan, une musique qui boucle et quelques raccourcis clavier.