Pausando jogos

Pausa?

Na maioria dos jogos, é desejável, em algum ponto, interromper o jogo para fazer outra coisa, como fazer uma pausa ou alterar opções. No entanto, isso não é tão simples quanto parece. O jogo pode ser interrompido, mas pode ser desejável que alguns menus e animações continuem funcionando.

Implementar um controle refinado para o que pode ser pausado (e o que não pode) é muito trabalhoso, portanto, uma estrutura simples para pausa é fornecida no Godot.

Como a pausa funciona

Para definir o modo de pausa, o estado de pausa deve ser definido. isso é feito atribuindo true à propriedade SceneTree.paused:

get_tree().paused = true
GetTree().Paused = true;

Fazer isso terá o seguinte comportamento:

  • As físicas 2D e 3D serão interrompidas.
  • _process e _physics_process não serão mais chamados nos nós.
  • _input e _input_event também não serão mais chamados.

Isso efetivamente interrompe todo o jogo. Chamar esta função a partir de um script, por padrão, resultará em um estado irrecuperável (nada funcionará mais!).

Adicionando nós à lista branca

Antes de habilitar a pausa, certifique-se de que os nós que devem continuar trabalhando durante a pausa estejam na lista branca. Isso é feito editando a propriedade "Modo de Pausa" em um nó:

../../_images/pausemode.png

Você pode alcançar o mesmo resultado em código:

func _ready():
    pause_mode = Node.PAUSE_MODE_PROCESS

Por padrão, todos os nós têm essa propriedade no estado "Inherit". Isso significa que eles só irão processar (ou não) dependendo do que esta mesma propriedade está definida no nó pai. Se o pai estiver definido como "Inherit", o avô será verificado e assim por diante. Por fim, se um estado não puder ser encontrado em nenhum dos avós, o estado de pausa em SceneTree será usado. Isso significa que, por padrão, quando o jogo é pausado, todos os nós serão pausados.

Assim, os três estados possíveis para um nó são:

  • Herdar: Processa dependendo do estado do pai, avô, etc. O primeiro pai que tem um estado não Inherit.
  • Stop: Para o nó não importa o que aconteça (e filhos no modo Inherit). Quando pausado, este nó não será processado.
  • Process: Processa o nó independentemente do que aconteça (e os filhos no modo Inherit). Pausado ou não, este nó será processado.

Exemplo

Um exemplo disso é criar um pop-up ou painel com controles internos e definir seu modo de pausa para "Process" e ocultá-lo:

../../_images/pause_popup.png

Apenas definindo a raiz do pop-up de pausa como "Process", todos os filhos e netos herdarão esse estado. Dessa forma, este ramo da árvore da cena continuará funcionando quando estiver em pausa.

Finalmente, faça isso quando um botão de pausa for pressionado (qualquer botão serve), habilite a pausa e mostre a tela de pausa.

func _on_pause_button_pressed():
    get_tree().paused = true
    $pause_popup.show()
public void _on_pause_button_pressed()
{
    GetTree().Paused = true;
    GetNode<Control>("pause_popup").Show();
}

Para remover a pausa, faça o oposto quando a tela de pausa for fechada:

func _on_pause_popup_close_pressed():
    $pause_popup.hide()
    get_tree().paused = false
public void _on_pause_popup_close_pressed()
{
    GetNode<Control>("pause_popup").Hide();
    GetTree().Paused = false;
}

E é isso!