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 e adicione um nó CanvasLayer chamado HUD. "HUD" significa "heads-up display", uma exibição informativa que aparece como uma sobreposição na parte superior da 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:

  1. Na propriedade "Custom Fonts" (Fontes Personalizadas), escolha "Nova DynamicFont"

../../_images/custom_font1.png
  1. Clique no "DynamicFont" que você adicionou e em Fonte > FontData, escolha "Carregar" e selecione o arquivo "Xolonium-Regular.ttf".

../../_images/custom_font2.png

Defina a propriedade "Size" em Settings, 64 funciona bem.

../../_images/custom_font3.png

Depois de fazer isso no `` ScoreLabel``, você pode clicar na seta para baixo ao lado da propriedade DynamicFont e escolher "Copiar", depois "Colar" no mesmo local que os outros dois nós de Controle.

Nota

Âncoras e Margens: Nós Control têm uma posição e um tamanho, mas eles também têm âncoras e margens. Âncoras definem a origem – o ponto de referência para as bordas do nó. Margens atualizam automaticamente quando você move ou redimensiona um nó de controle. Elas representam a distância das bordas do nó Control até sua âncora. Veja doc_design_interfaces_with_the_control_nodes para mais detalhes.

Organize os nós conforme indicado abaixo. Clique no botão "Disposição (Layout)" para definir a disposição de um nó de controle:

../../_images/ui_anchor.png

Você pode arrastar os nós para colocá-los manualmente ou, para um posicionamento mais preciso, usar as seguintes configurações:

ScoreLabel

  • Layout : "Top Wide"

  • Texto: 0

  • Alinhamento : "Centralizado"

Mensagem

  • Layout : "Center" (Centro)

  • Text: Desvie dos Bichos!

  • Alinhamento : "Centralizado"

  • Autowrap : "Ativo"

StartButton

  • Text: Iniciar

  • Layout: "Center Bottom"

  • Margem (Margin) :

    • Top: -200

    • Inferior: -100

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

signal start_game

O sinal start_game diz ao nó Main que o botão foi pressionado.

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

Esta função é chamada quando queremos mostrar uma mensagem temporariamente, como a "Prepare-se".

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()

Esta função é chamada quando o jogador perde. Ela mostrará "Game Over" por 2 segundos e depois retornará à tela de título após uma breve pausa e mostrará o botão "Iniciar".

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".

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

Esta função é chamada por ``Main``sempre que a pontuação for alterada.

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

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

func _on_MessageTimer_timeout():
    $Message.hide()

Conectando HUD a Principal

Agora que terminamos de criar a cena HUD, salve-a e volte para a Principal. Crie uma instância da cena HUD como fez com a cena Jogador, e coloque-a no final da árvore. A árvore completa deveria se parecer assim, então confira se não falta alguma coisa:

../../_images/completed_main_scene.png

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

Na guia Nó, conecte o sinal `` start_game`` do HUD à função `` new_game () `` do nó Principal, digitando "new_game" no "Receiver Method" na janela "Connect a Signal". Verifique se o ícone de conexão verde agora aparece 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()

Finalmente, adicione isto a _on_ScoreTimer_timeout() para manter o mostrador em sincronia com as mudanças de pontuação:

$HUD.update_score(score)

Agora está tudo pronto para jogar! Clique no botão "Rodar o Projeto". Será solicitada a seleção de uma cena principal, então escolha Principal.tscn.

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 do Inimigo, selecione o nó raiz e clique na aba "Nó" próxima ao Inspetor(No mesmo lugar onde vocÊ encontra os sinais do nó). Próximo a "Sinais", clique "Grupos", você pode digitar o nome do novo grupo e clicar em "Adicionar".

../../_images/group_tab.png

Agora todos os inimigos estarão no grupo "inimigos". Podemos então adicionar a seguinte linha à função game_over() 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.