Pular para o conteúdo
Jogos Digitais
Nesta página
  1. Objetivos de aprendizagem
  2. Pré-requisitos
  3. Materiais
  4. Conceitos
  5. Exemplos
  6. Tutorial passo a passo
  7. Imagens
  8. Indicação da interface
  9. O código completo
  10. Explicação do código
  11. Resultado esperado
  12. Problemas comuns
  13. Exercício guiado
  14. Desafio individual
  15. Desafio avançado (opcional)
  16. Critérios de avaliação
  17. Checklist de conclusão
  18. Extensão

Módulo 9 · Aula 9.6 · Chave, porteira e saída

Carga horáriaDificuldadeFerramentaCompetências
8 h/a⭐⭐⭐Godot 4.7C2, C3

Objetivos de aprendizagem

  1. Usar Area3D e o sinal body_entered em 3D (igual ao 2D).
  2. Separar quem avisa (chave, porteira, saída) de quem decide (cena do labirinto).
  3. Abrir uma porta com Tween e desligar a colisão com set_deferred.
  4. Guardar o melhor tempo, em que o menor número vence.

Pré-requisitos

Aulas 9.3 a 9.5; Aulas 8.4 (sinais), 8.6 (Autoload) e 8.9 (Tween).

Materiais

Godot 4.7; chave-da-porteira (cenas/chave.tscn, porteira.tscn, saida.tscn, scripts/labirinto.gd, scripts/global.gd).

Conceitos

Mesma ideia do Sementes. A semente avisava coletada e a cena do jogo contava o ponto. Aqui:

Chave    --body_entered--> chave.gd    --pega-------------------> labirinto.gd: _on_chave_pega
Porteira/Perto --body_entered--> porteira.gd --jogador_chegou(jogador)--> labirinto.gd: _on_porteira_jogador_chegou
Saida    --body_entered--> saida.gd    --jogador_saiu-----------> labirinto.gd: _on_saida_jogador_saiu

A porteira não decide. Quando alguém chega perto, ela só avisa quem chegou. A cena do labirinto olha tem_chave e manda abrir, ou mostra o aviso "A porteira está trancada. Ache a chave!". Assim, numa fase nova, a mesma porteira pode abrir com outra regra (três castanhas, um botão).

Corpo e área juntos. A porteira tem duas partes: um StaticBody3D (Corpo), que bloqueia o caminho, e uma Area3D (Perto), maior, que percebe quem se aproxima dos dois lados.

Dobradiça. Para a porta girar pela ponta, e não pelo meio, ela fica dentro de um nó vazio Dobradica posto na ponta. Gira-se a dobradiça, e a porta vai junto. É o mesmo truque de pivô da animação no Módulo 5.

set_deferred. Desligar a colisão bem na hora em que a física está conferindo encontros dá erro (lembra do call_deferred da Aula 8.5?). colisao.set_deferred("disabled", true) deixa para o fim do quadro.

Menor tempo vence. No Sementes, recorde era o maior número de pontos. Aqui é o menor tempo. E o primeiro tempo de todos precisa virar recorde, por isso melhor_tempo começa em 0, que quer dizer "ainda não tem".

Exemplos

SituaçãoO que aconteceConferido no teste
chega na porteira sem chaveaviso de trancada; a porteira segura o jogadorsim
encosta na chavechave some; placar "Chave: achou!"sim
chega na porteira com chavecolisão desligada; a porta gira 100° em 0,8 ssim
pisa na saídatela de fim com o tempo e o melhor temposim
tempo pior que o melhoro melhor não mudasim

Tutorial passo a passo

Parte A. Ler as três cenas (80 min)

  1. Abra chave.tscn: Area3D com esfera de colisão, argola (TorusMesh), haste e dente, e um OmniLight3D (Brilho) que faz a chave chamar atenção no corredor.
  2. Abra porteira.tscn e selecione Perto (captura): a caixa da área é mais funda que a porta, para perceber de longe.
  3. Abra saida.tscn: disco verde com emissão e um Label3D "SAÍDA" que sempre vira para a câmera (Billboard).
  4. Em labirinto.tscn, selecione Porteira e veja na aba Sinais o jogador_chegou ligado à cena.

Parte B. Fazer funcionar no seu labirinto (160 min)

  1. Copie as três cenas e os três scripts para o seu projeto da Aula 9.5 e instancie cada uma (Instanciar Cena Filha...).
  2. Conecte os três sinais à cena do labirinto pela aba Sinais e escreva as três funções (código abaixo).
  3. Jogue: tente abrir sem chave, pegue a chave, abra, saia.

Parte C. Melhor tempo (80 min)

  1. Leia global.gd. Explique para a dupla o if melhor_tempo == 0.0 or tempo < melhor_tempo.
  2. Jogue três vezes. A tela de fim mostra o melhor tempo certo?

Imagens

  • ../../../recursos/imagens/godot/chave-da-porteira-tela-trancada.png: chegando sem chave.
  • ../../../recursos/imagens/godot/chave-da-porteira-tela-aberta.png: porteira aberta, saída à vista.
  • ../../../recursos/imagens/godot/chave-da-porteira-tela-fim.png: tempo e melhor tempo.
  • ../../../recursos/imagens/godot/captura-godot3d-porteira.png: a cena da porteira com Perto selecionado.

Indicação da interface

ItemNome na tela
sinais do nóaba Sinais, Conectar...
instanciarInstanciar Cena Filha...
texto 3D que olha para a câmeranó Label3D, propriedade Billboard

O código completo

scripts/porteira.gd:

extends Node3D
## Porteira de madeira. Ela não decide nada: só avisa que o jogador chegou perto
## e sabe se abrir quando mandam.

signal jogador_chegou(jogador: Node3D)

var aberta := false

@onready var dobradica: Node3D = $Dobradica
@onready var colisao: CollisionShape3D = $Dobradica/Corpo/Colisao


func _on_perto_body_entered(corpo: Node3D) -> void:
	if corpo.is_in_group("jogador"):
		jogador_chegou.emit(corpo)


func abrir() -> void:
	if aberta:
		return
	aberta = true
	# Mexer em colisão no meio da física pede set_deferred (como o call_deferred do Módulo 8).
	colisao.set_deferred("disabled", true)
	var tween := create_tween()
	tween.tween_property(dobradica, "rotation_degrees:y", 100.0, 0.8)

Trecho de scripts/labirinto.gd:

func mostrar_aviso(texto: String) -> void:
	aviso.text = texto
	aviso.show()
	await get_tree().create_timer(2.5).timeout
	if aviso.text == texto:
		aviso.hide()


func _on_chave_pega() -> void:
	jogador.tem_chave = true
	texto_chave.text = "Chave: achou!"
	mostrar_aviso("Achou a chave! Agora procure a porteira.")


func _on_porteira_jogador_chegou(quem: Node3D) -> void:
	if quem.tem_chave:
		porteira.abrir()
	else:
		mostrar_aviso("A porteira está trancada. Ache a chave!")


func _on_saida_jogador_saiu() -> void:
	if terminou:
		return
	terminou = true
	Global.terminar_partida(tempo)
	get_tree().change_scene_to_file.call_deferred("res://cenas/fim.tscn")

Trecho de scripts/global.gd:

func terminar_partida(tempo: float) -> void:
	tempo_da_partida = tempo
	if melhor_tempo == 0.0 or tempo < melhor_tempo:
		melhor_tempo = tempo
		salvar_recorde()

Explicação do código

  • signal jogador_chegou(jogador: Node3D) é um sinal que leva um valor: quem chegou. Era o desafio da semente dourada na Aula 8.4.
  • rotation_degrees:y deixa o Tween mexer só no giro em volta do Y.
  • Em mostrar_aviso, o if aviso.text == texto evita que um aviso velho apague um aviso novo que apareceu nesse meio-tempo.
  • terminou impede que pisar duas vezes na saída grave o tempo duas vezes.

Resultado esperado

Chave, porteira e saída funcionando no labirinto do aluno, com avisos na tela e melhor tempo salvo.

Problemas comuns

SintomaCausaSolução
a porteira nunca avisaPerto pequeno demais, ou sinal não conectadoconferir a caixa da área e a aba Sinais
a porta gira pelo meiogirou o Corpo em vez da Dobradicagirar o nó da ponta
porta aberta, mas continua batendocolisão não desligadaset_deferred("disabled", true)
o primeiro tempo nunca vira recordemelhor_tempo começa em 0 e o if só olha tempo < melhor_tempoincluir melhor_tempo == 0.0 or
a chave some quando a câmera passaa chave não confere o grupois_in_group("jogador")

Exercício guiado

Na preparação, o teste "porteira abre com a chave" falhou na primeira vez. O jogo estava certo: o teste colocava o jogador a 2,7 m da porteira, fora da caixa Perto, que vai só até 2,2 m. Como o teste poderia ter avisado isso mais cedo? (Resposta possível: conferindo primeiro o aviso de trancada, que também depende da área; ele falhou junto e apontava para a posição.)

Desafio individual

Faça a porteira dar um aviso diferente quando o jogador chega pela segunda vez sem chave ("Ainda trancada...").

Desafio avançado (opcional)

Coloque duas chaves e duas porteiras, cada chave abrindo só a sua (dica: um @export var cor := "azul" na chave e na porteira).

Critérios de avaliação

  • Os três sinais funcionando no labirinto próprio.
  • Explica por que a porteira não decide sozinha.
  • Melhor tempo com menor número vencendo.

Checklist de conclusão

Extensão

Liste três coisas de um jogo que você conhece que "avisam" e quem "decide" o que fazer com o aviso.