L’arbre de scène

Introduction

Dans le tutoriel précédent, chaque chose tournais autour du concept des nœuds. Chaque scène est simplement une collection de nœud. Elles deviennent actives une fois entrée dans l’arbre de scène.

Boucle événementielle

La façon dont Godot fonctionne en interne est la suivante : Au départ, la seule instance qui fonctionne est la classe OS, ensuite, tous les pilotes, serveurs, langages de script, système de gestion de scènes … sont chargés.

Quand l’initialisation est terminée, une MainLoop pour fonctionner. Jusqu’à ce point, tout ceci est du fonctionnement interne (vous pouvez consulter le fichier main/main.cpp dans le code source si jamais vous ètes intéressé de voir comment cela fonctionne en interne).

Le programme utilisateur, ou le jeu, démarre dans la boucle événementielle. Cette classe a quelques méthodes, pour l’initialisation, l’inactivité (rappel synchronisé par trame), fixe (rappel synchronisé par la physique) et les entrées. Encore une fois, ceci est bas niveau et lorsque vous créez des jeux avec Godot, écrire votre propre boucle événementielle a rarement du sens.

L’arbre de scène

L’un des manières d’expliquer comment Godot fonctionne est qu’il est un moteur de jeu de haut niveau, construit par-dessus un middleware de bas niveau.

Le système de gestion de scènes et le « game engine » proprement dit tandis que la OS et les serveurs font partis de l’API de bas niveau.

Le système de scène fournit sa propre boucle principale à l’OS, SceneTree. Ceci est automatiquement instancié et configuré lors de l’exécution d’une scène, aucun travail supplémentaire est nécessaire.

Il est important de savoir que cette classe existe car elle a des utilisations importantes :

  • Elle contient la racine Viewport, à laquelle une scène est ajoutée en tant qu’enfant lorsqu’elle est ouverte pour la première fois, afin de faire partie de l’arborescence de scène (Scene Tree) (plus d’informations là-dessus par la suite)
  • Elle contient des informations sur les groupes et permet d’appeler tous les nœuds d’un groupe ou d’obtenir une liste de ceux-ci.
  • Elle contient certaines fonctionnalités d’état global, comme le réglage du mode pause ou l’abandon du processus.

Lorsqu’un nœud fait partie de l’arbre des scènes, le singleton SceneTree peut être obtenu en appelant simplement Node.get_tree().

La fenêtre d’affichage racine

La racine Viewport est toujours en haut de la scène. A partir d’un nœud, elle peut être obtenu de deux manières différentes :

get_tree().get_root() # Access via scene main loop.
get_node("/root") # Access via absolute path.
GetTree().GetRoot(); // Access via scene main loop.
GetNode("/root"); // Access via absolute path.

Ce nœud contient la vue principale, tout ce qui est un enfant d’un Viewport est dessiné à l’intérieur de celui-ci par défaut, il est donc logique que le nœud en amont de tous les autres soit toujours un nœud de ce type, sinon rien ne serait vu.

Alors que d’autres fenêtres d’affichage peuvent être créées dans la scène (pour des effets d’écran partagé et autres), celle-ci est la seule qui n’est jamais créée par l’utilisateur. Elle est créée automatiquement à l’intérieur de SceneTree.

Arbre de scène

Lorsqu’un nœud est connecté, directement ou indirectement, à la vue racine, il fait partie de l’arborescence des scènes.

Cela signifie que, comme expliqué dans les tutoriels précédents, il recevra les rappels de _enter_tree() et _ready() (ainsi que _exit_tree()).

../../_images/activescene.png

Lorsque les nœuds entrent dans l”arbre de scène, ils deviennent actifs. Ils ont accès à tout ce dont ils ont besoin pour traiter, obtenir des entrées, afficher des données en 2D et 3D, recevoir et envoyer des notifications, jouer du son, etc. Lorsqu’ils sont retirés de l”arbre de scène, ils perdent cet accès.

Ordre de l’arborescence

La plupart des opérations de nœuds dans Godot, comme le dessin 2D, le traitement ou l’obtention de notifications se font dans l’ordre de l’arborescence. Cela signifie que les parents et les frères et sœurs ayant un rang inférieur dans l’ordre de l’arborescence seront notifiés avant le nœud courant.

../../_images/toptobottom.png

« Activation » en entrant dans l”arbre de scène

  1. Une scène est chargée à partir du disque ou créée par un script.
  2. Le nœud racine de cette scène (une seule racine, vous souvenez-vous ?) est ajouté soit comme un enfant de la fenêtre d’affichage Viewport « racine » (de SceneTree), soit à tout enfant ou petit-enfant de celle-ci.
  3. Chaque nœud de la scène nouvellement ajoutée recevra la notification « enter_tree » (fonction de rappel _enter_tree() dans GDScript) dans l’ordre haut vers bas.
  4. Une notification supplémentaire, « ready » (fonction de rappel _ready() dans GDScript) est fournie par commodité, lorsqu’un nœud et tous ses enfants sont à l’intérieur de la scène active.
  5. Quand une scène (ou une partie de celle-ci) est enlevée, ils reçoivent la notification « exit scene » (fonction de rappel _exit_tree() dans GDScript), du nœud le plus bas vers celui le plus haut

Changement de la scène courante

Après qu’une scène soit chargée, il est souvent souhaitable de la remplacer par une autre. La façon la plus simple de le faire est d’utiliser la fonction SceneTree.change_scene() :

func _my_level_was_completed():
    get_tree().change_scene("res://levels/level2.tscn")
public void _MyLevelWasCompleted()
{
    GetTree().ChangeScene("res://levels/level2.tscn");
}

Au lieu d’utiliser des chemins de fichiers, vous pouvez aussi utiliser la ressource déjà prête PackedScene en utilisant la fonction équivalente SceneTree.change_scene_to(PackedScene scene) :

var next_scene = preload("res://levels/level2.tscn")

func _my_level_was_completed():
    get_tree().change_scene_to(next_scene)
public void _MyLevelWasCompleted()
{
    var nextScene = (PackedScene)ResourceLoader.Load("res://levels/level2.tscn");
    GetTree().ChangeSceneTo(nextScene);
}

Ce sont des façons rapides et utiles de passer d’une scène à une autre mais qui ont l’inconvénient que le jeu va devoir attendre jusqu’à ce que la nouvelle scène soit chargée et fonctionne. À un moment donné, dans le développement de votre jeu, vous souhaiterez peut-être créer des écrans de chargement avec des barres de progression, indicateurs animés ou chargement en arrière plan. Cela doit être fait manuellement en utilisant des « autoloads » (voir le chapitre suivant !) et Background loading.