Usando Árvore de cena

Introdução

Nos tutoriais anteriores, tudo girava em torno do conceito de nós. Cenas são simplesmente uma coleção de nós. Elas se tornam ativos quando entram na árvore de cena.

Loop principal

A maneira como o Godot trabalha internamente é a seguinte. Há a classe OS, que é a única instância que é executada no início. Depois, todos os drivers, servidores, linguagens de script, sistema de cena, etc. são carregados.

Quando a inicialização estiver completa, OS precisa de um MainLoop para ser executado. Até este ponto, tudo isso é funcionamento interno (você pode verificar o arquivo main/main.cpp no código-fonte, se você estiver interessado em ver como isso funciona internamente).

O programa do usuário, ou jogo, inicia no MainLoop. Essa classe tem alguns métodos, para inicialização, ocioso (retorno de chamada com sincronia de quadros), fixo (retorno de chamada com sincronização física) e entrada. Novamente, isso é de baixo nível e ao fazer jogos no Godot, escrever seu próprio MainLoop raramente faz sentido.

SceneTree

Uma das maneiras de explicar como Godot funciona é que é um mecanismo de jogo de alto nível sobre um middleware de baixo nível.

O sistema de cena é o mecanismo do jogo, enquanto o OS e os servidores são a API de baixo nível.

O sistema de cena fornece seu próprio loop principal para o SO, SceneTree. Isso é automaticamente instanciado e definido ao executar uma cena, sem necessidade de qualquer trabalho extra.

É importante saber que essa classe existe porque tem alguns usos importantes:

  • Ele contém o Viewport raiz, para o qual uma cena é adicionada como filha quando é aberta pela primeira vez, para se tornar parte da Árvore da Cena (mais sobre isso a seguir).

  • Ele contém informações sobre os grupos e tem meios para chamar todos os nós de um grupo ou obter uma lista deles.

  • Ela contém alguma funcionalidade de estado global, como configurar o modo de pausa ou encerrar o processo.

Quando um nó é parte da Scene Tree, o singleton SceneTree pode ser obtido chamando Node.get_tree().

Viewport raiz

A raiz Viewport está sempre no topo da cena. De um nó, ela pode ser obtida de duas maneiras diferentes:

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

Este nó contém a janela de exibição principal. Qualquer coisa que é filho de uma Viewport é desenhada dentro dele por padrão, então faz sentido que o topo de todos os nós seja sempre um nó deste tipo, caso contrário nada seria visto.

Enquanto outras viewports podem ser criadas na cena (para efeitos de tela dividida e tal), esta é a única que nunca é criada pelo usuário. É criado automaticamente dentro do SceneTree.

Árvore de cena

Quando um nó é conectado, direta ou indiretamente, à viewport raiz, ele se torna parte da árvore de cena.

Isto significa que, como explicado em tutoriais anteriores, receberá as ligações _enter_tree() e _ready() (assim como _exit_tree()).

../../_images/activescene.png

Quando os nós entram na Scene Tree, eles se tornam ativos. Eles têm acesso a tudo o que precisam para processar, obter entrada, exibir visuais em 2D e 3D, enviar e receber notificações, reproduzir sons, etc. Quando são removidos da árvore de cena, eles perdem essas habilidades.

Ordem da árvore

A maioria das operações de nó no Godot, como desenhar 2D, processar, ou obter notificações, é feita em ordem de árvore. Isso significa que pais e irmãos com uma classificação menor na ordem de árvore serão notificados antes do nó atual.

../../_images/toptobottom.png

"Tornando-se ativo" entrando na * Scene Tree *

  1. Uma cena é carregada do disco ou criada pelo script.

  2. O nó raiz dessa cena (apenas uma raiz, lembra?) É adicionado como um filho da viewport "root" (de SceneTree), ou para qualquer filho ou neto dela.

  3. Cada nó da cena recém-adicionada receberá a notificação "enter_tree" (callback _enter_tree() em GDScript) na ordem de cima para baixo.

  4. Uma notificação extra, "ready" (retorno de chamada _ready() em GDScript) é fornecida por conveniência, quando um nó e todos os seus filhos estão dentro da cena ativa.

  5. Quando uma cena (ou parte dela) é removida, eles recebem a notificação "exit scene" (retorno de chamada _exit_tree() em GDScript) na ordem de baixo para cima

Alterando a cena atual

Depois que uma cena é carregada, muitas vezes é desejado mudar essa cena para outra. A maneira simples de fazer isso é usar a função SceneTree.change_scene():

func _my_level_was_completed():
    get_tree().change_scene("res://levels/level2.tscn")

Em vez de usar caminhos de arquivo, também é possível utilizar recursos prontos PackedScene usando a função equivalente SceneTree.change_scene_to(cena PackedScene):

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

func _my_level_was_completed():
    get_tree().change_scene_to(next_scene)

Estas são maneiras rápidas e úteis de trocar de cena, mas têm a desvantagem de o jogo travar até que a nova cena seja carregada e executada. Em algum momento do seu jogo, pode ser necessário criar telas de carregamento adequadas com barra de progresso, indicadores animados ou carregamento de thread (no fundo). Isso deve ser feito manualmente usando autoloads (veja o próximo capítulo) e Carregamento em segundo plano.