Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

Monitor de alerta

A peça final que nosso jogo precisa é uma Interface de Usuário (UI) para exibir coisas como pontuação, uma mensagem de "game over" e um botão de reiniciar.

Crie uma nova cena, clique no botão "Other Node" e adicione um nó CanvasLayer chamado HUD. "HUD" significa "heads-up display", uma interface informativa exibida como uma sobreposição sobre a visualização do jogo.

O nó CanvasLayer nos permite desenhar nossos elementos de interface em uma camada acima do resto do jogo, de forma que as informações que ela mostrar não fiquem cobertas por quaisquer elementos do jogo, como o jogador ou os inimigos.

O HUD exibirá as seguintes informações:

  • Pontuação, alterado para ScoreTimer.

  • Uma mensagem, como "Game Over" ou "Prepare-se!"

  • Um botão "Iniciar" para começar o jogo.

O nó básico para elementos de interface é Control. Para criar nossa interface, usaremos dois tipos de nós Control: Label e Button.

Crie os seguintes itens como filhos do nó HUD:

  • Label nomeado ScoreLabel.

  • Label nomeado MessageLabel.

  • Button nomeado StartButton.

  • Timer nomeado MessageTimer.

Clique no ScoreLabel e digite um número no campo Text``no Inspetor. A fonte padrão para os nós ``Control é pequena e não escala bem. Há um arquivo de fonte incluído nos assets do jogo chamado "Xolonium-Regular.ttf". Para usar esta fonte, faça o seguinte para cada um dos três nós Control:

Em "Theme Overrides > Fonts", escolha "Load" e selecione o arquivo "Xolonium-Regular.ttf".

../../_images/custom_font_load_font.webp

O tamanho da fonte ainda está muito pequeno; aumente-o para 64 em "Theme Overrides > Font Sizes". Depois de fazer isso no nó ScoreLabel, repita as alterações nos nós Message e StartButton.

../../_images/custom_font_size.webp

Nota

Âncoras: Os nós Control têm uma posição e um tamanho, mas também têm âncoras. As âncoras definem a origem - o ponto de referência para as laterais do nó.

Organize os nós conforme mostrado abaixo. Você pode arrastar os nós para posicioná-los manualmente ou, para um posicionamento mais preciso, usar "Predefinições de âncora".

../../_images/ui_anchor.webp

ScoreLabel

  1. Adicione o texto 0.

  2. Defina o "Alinhamento Horizontal" e "Alinhamento Vertical" para Center.

  3. Escolha a "Predefinição de Âncora" Centro Superior.

Mensagem

  1. Adicione o texto Dodge the Creeps!.

  2. Defina o "Alinhamento Horizontal" e "Alinhamento Vertical" para Center.

  3. Defina o "Modo Autowrap" para Word, caso contrário o rótulo permanecerá em uma linha.

  4. Em "Control - Layout/Transform", defina "Size X" como 480 para usar toda a largura da tela.

  5. Escolha a "Predefinição de Âncora" Centro.

StartButton

  1. Adicione o texto: Iniciar.

  2. Em "Control - Layout/Transform", defina "Size X" como 200 e "Size Y" como 100 para adicionar um pouco mais de espaçamento entre a borda e o texto.

  3. Escolha a "Predefinição de Âncora" Centro Inferior.

  4. Em "Control - Layout - Transform", defina "Y" de "Position" para 580.

No MessageTimer, defina o Wait Time (Tempo de Espera) para 2 e configure a propriedade One Shot (Apenas uma Vez) como "Ativo".

Agora, adicione este script ao HUD:

extends CanvasLayer

# Notifies `Main` node that the button has been pressed
signal start_game

Agora queremos exibir uma mensagem temporária, como "Prepare-se", então vamos adicionar o seguinte código

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

Também precisamos processar o que acontece quando o jogador perde. O código abaixo exibirá "Game Over" por 2 segundos, depois retornará à tela de título e, após uma breve pausa, mostrará o botão "Start".

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

    $Message.text = "Dodge the Creeps!"
    $Message.show()
    # Make a one-shot timer and wait for it to finish.
    await get_tree().create_timer(1.0).timeout
    $StartButton.show()

Nota

Quando você precisa pausar por um breve tempo, uma alternativa ao do nó Timer é usar a função create_timer() do SceneTree. Isso pode ser muito útil para atrasar, como no código acima, onde queremos esperar um pouco de tempo antes de mostrar o botão "Iniciar".

Adicione o código abaixo no HUD para atualizar a pontuação

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

Conecte o sinal pressed() do StartButton e o sinal timeout() do MessageTimer ao nó HUD, e adicione o seguinte código às novas funções:

func _on_start_button_pressed():
    $StartButton.hide()
    start_game.emit()

func _on_message_timer_timeout():
    $Message.hide()

Conectando HUD a Principal

Now that we're done creating the HUD scene, go back to Main. Instantiate the HUD scene in Main like you did the Player scene. The scene tree should look like this, so make sure you didn't miss anything:

../../_images/completed_main_scene.webp

Agora precisamos conectar a funcionalidade de HUD ao roteiro de Principal. Isso exige algumas adições à cena Principal:

Na aba Signals, conecte o sinal start_game do HUD à função new_game() do nó Main clicando no botão "Pick" na janela "Connect a Signal" e selecionando o método new_game() ou digite "new_game" abaixo de "Receiver Method" na janela. Verifique se o ícone verde de conexão aparece agora ao lado de func new_game() no script.

Em new_game(), atualize o mostrador de pontuação e mostre a mensagem "Prepare-se":

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

Em game_over(), precisamos chamar a correspondente função de HUD:

$HUD.show_game_over()

Por fim, adicione isto a _on_score_timer_timeout() para manter a exibição sincronizada com a mudança da pontuação:

$HUD.update_score(score)

Aviso

Lembre-se de remover a chamada para new_game() de _ready() caso ainda não tenha feito isso; caso contrário, seu jogo iniciará automaticamente.

Agora você está pronto para jogar! Clique no botão "Play the Project".

Removendo antigas criaturas

Se você jogar até o "Game Over" e iniciar um novo jogo, as criaturas do jogo anterior ainda poderão estar na tela. Seria melhor se todas elas desaparecessem no iníco de cada partida. Nós só precisamos de um jeito de falar para todos os inimigos se auto-destruirem. Nós podemos fazer isso com a funcionalidade "group"(grupo).

Na cena Mob, selecione o nó raiz e clique na aba Groups ao lado da aba Signals e no botão "+" para abrir a janela "Create New Group".

../../_images/group_tab.webp

Dê o nome mobs ao grupo e clique em "ok" para adicionar um novo grupo de cena.

../../_images/add_group_dialog.webp

Agora todos os mobs estarão no grupo "mobs".

../../_images/scene_group_mobs.webp

Em seguida, podemos adicionar a seguinte linha à função new_game() em Main:

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

A função call_group() chama a função passada como parâmetro em cada nó do grupo - neste caso nós estamos falando para cada inimigo se auto-destruir.

O jogo está quase pronto nesse ponto. Na próxima e última parte, daremos um melhor acabamento adicionando um plano de fundo, música em "looping", e alguns atalhos de teclado.