Módulo 8 · Aula 8.6 · Telas, Autoload e recorde salvo
| Carga horária | Dificuldade | Ferramenta | Competências |
|---|---|---|---|
| 10 h/a | ⭐⭐⭐ | Godot 4.7 | C2, C3 |
Objetivos de aprendizagem
- Montar telas com nós de interface (
Control,Label,TextureRect) e um placar por cima do jogo (CanvasLayer). - Trocar de cena com
get_tree().change_scene_to_file(). - Guardar dados que passam de uma cena para outra num Autoload.
- Salvar e carregar o recorde num arquivo (
FileAccess, pastauser://). - Esperar 1 segundo com
awaitantes de aceitar a tecla na tela de fim.
Pré-requisitos
Aulas 8.4 e 8.5. Aula 6.5 (salvar progresso no GDevelop).
Materiais
Godot 4.7; Sementes em Godot (inicio.tscn, fim.tscn, global.gd).
Conceitos
Nós de interface. Ficam em verde na árvore. Control é a base; Label mostra texto; TextureRect mostra imagem; Button é botão. Uma tela inteira (início, fim) pode ter raiz Control.
CanvasLayer. Uma camada que fica sempre por cima e não se mexe com a câmera. O placar do jogo fica dentro de uma CanvasLayer chamada Interface, como a camada de interface do GDevelop (Aula 4.2).
Trocar de cena. get_tree().change_scene_to_file("res://cenas/jogo.tscn") fecha a cena atual e abre outra. Tudo o que estava na cena atual some, inclusive as variáveis dos scripts dela.
Autoload. Um script que o Godot carrega antes de tudo e que não some ao trocar de cena. Ele fica disponível em qualquer script pelo nome escolhido (no Sementes, Global). Configura-se em Configurações do Projeto... → aba Globais → Autoload. É o papel das variáveis globais do GDevelop.
user://. Pasta de dados do jogo no computador do jogador (no Windows, dentro da pasta de dados do usuário). O menu Projeto → Abrir Pasta de Dados do Usuário abre essa pasta. É aqui que o recorde é salvo, porque res:// vira só leitura depois de exportar.
Recorde em arquivo. No GDevelop (Módulo 3) o recorde era só da sessão. Aqui ele fica num arquivo e continua lá depois de fechar o jogo:
var arquivo := FileAccess.open("user://recorde.save", FileAccess.WRITE)
arquivo.store_var(recorde)await: esperar sem travar. await get_tree().create_timer(1.0).timeout espera 1 segundo e continua a função dali. O resto do jogo segue rodando nesse meio-tempo.
Exemplos
| Pergunta | Onde guardar |
|---|---|
| pontos da partida que a tela de fim precisa mostrar | Autoload (Global.pontos) |
| recorde que deve valer amanhã | arquivo em user:// |
| vidas, que só importam durante a partida | variável no script do jogo |
Tutorial passo a passo
Parte A. Autoload (90 min)
- No Sementes, abra Configurações do Projeto... → Globais → Autoload e veja
Globalcomres://scripts/global.gd(captura abaixo). - Leia
global.gd. Por quepontosestá aqui evidasestá emjogo.gd? - No seu projeto, crie
global.gdcomvar pontos := 0e registre como Autoload com Selecionar Script/Cena. Confira na coluna Nome que ficouGlobal. (A captura mostra a aba com o Autoload já registrado; o passo de adicionar não foi fotografado nesta versão, e o professor deve fazê-lo uma vez antes da aula.)
Parte B. Telas (150 min)
- Cena
inicio.tscncom raizControl, umTextureRectde fundo e doisLabel(título e instruções). - Script
inicio.gd: na açãocomecar(Espaço e Enter, no Mapa de Entrada) ou num clique, troca parajogo.tscn. - Cena
fim.tscnigual, com umLabelchamadoResultado. - No jogo, quando acabar o tempo ou as vidas, chame
terminar(). - Defina
inicio.tscncomo cena principal (Aula 8.1) e jogue do começo ao fim.
Parte C. Recorde salvo (120 min)
- Acrescente
recorde,salvar_recorde(),carregar_recorde()eterminar_partida()noglobal.gd. - Jogue, feche o jogo, abra de novo: o recorde continua?
- Use Abrir Pasta de Dados do Usuário e ache o arquivo
recorde.save. Apague e veja o recorde voltar a 0.
Parte D. A espera da tela de fim (60 min)
- Sem a espera de 1 segundo, quem estava apertando Espaço no fim da partida pula a tela de fim sem ver o resultado. Faça a espera com
awaite a variávelpode_sair.
Imagens
../../../recursos/imagens/godot/captura-godot-autoload-global.png
: aba Globais com o Autoload Global.../../../recursos/imagens/godot/sementes-godot-tela-inicio.png
e sementes-godot-tela-fim.png: as telas rodando.
Indicação da interface
| Item | Nome na tela |
|---|---|
| Autoload | Configurações do Projeto... → aba Globais → Autoload; botões Selecionar Script/Cena, Criar Script, Criar Cena; colunas Nome, Caminho, Variável Global (caixa Habilitar) |
pasta user:// | menu Projeto → Abrir Pasta de Dados do Usuário |
| cena principal | Configurações do Projeto... → Geral → Application → Run → Main Scene |
| nova cena de interface | Criar Nó Raiz: → Interface de Usuário |
O código completo
scripts/global.gd (Autoload Global):
extends Node
const ARQUIVO_RECORDE := "user://recorde.save"
var pontos := 0
var recorde := 0
func _ready() -> void:
carregar_recorde()
func terminar_partida() -> void:
if pontos > recorde:
recorde = pontos
salvar_recorde()
func salvar_recorde() -> void:
var arquivo := FileAccess.open(ARQUIVO_RECORDE, FileAccess.WRITE)
arquivo.store_var(recorde)
func carregar_recorde() -> void:
if FileAccess.file_exists(ARQUIVO_RECORDE):
var arquivo := FileAccess.open(ARQUIVO_RECORDE, FileAccess.READ)
recorde = arquivo.get_var()scripts/fim.gd:
extends Control
var pode_sair := false
@onready var resultado: Label = $Resultado
func _ready() -> void:
var palavra := "semente" if Global.pontos == 1 else "sementes"
resultado.text = "Você recolheu %d %s.\nRecorde: %d" % [Global.pontos, palavra, Global.recorde]
await get_tree().create_timer(1.0).timeout
pode_sair = true
func _unhandled_input(event: InputEvent) -> void:
if not pode_sair:
return
var clicou: bool = event is InputEventMouseButton and event.pressed
if event.is_action_pressed("comecar") or clicou:
get_tree().change_scene_to_file("res://cenas/jogo.tscn")Em jogo.gd, o fim:
func terminar() -> void:
Global.terminar_partida()
get_tree().change_scene_to_file.call_deferred("res://cenas/fim.tscn")Explicação do código
store_vareget_varguardam e leem um valor do jeito que ele é (aqui, um número).- O arquivo só é lido se existir: na primeira vez, o recorde fica 0.
\nno texto é uma quebra de linha.- A palavra "semente" muda para o singular quando é 1 (o teste confere "Você recolheu 1 semente.").
- A troca de cena no fim usa
call_deferredporque pode acontecer no meio de uma colisão (o redemoinho tirou a última vida).
Resultado esperado
Jogo completo: início, partida com placar, fim com pontos e recorde que continua salvo depois de fechar.
Problemas comuns
| Sintoma | Causa | Solução |
|---|---|---|
Identifier "Global" not declared | Autoload não registrado, ou com outro nome | registrar na aba Globais com o nome Global |
| pontos zeram na tela de fim | pontos guardados no script do jogo | guardar no Autoload |
| recorde não fica salvo | salvou em res:// | usar user:// |
| a tela de fim some na hora | tecla ainda apertada no fim | esperar 1 s com await |
Exercício guiado
Onde guardar o nome que o jogador digita no início, para mostrar no fim? E se quisermos lembrar o nome amanhã? (Resposta: no Autoload; para amanhã, também num arquivo em user://.)
Desafio individual
Mostre na tela de início o recorde atual ("Recorde: 12").
Desafio avançado (opcional)
Guarde os 3 melhores resultados numa lista (Array) e mostre um ranking na tela de fim. Dica: store_var também guarda listas.
Critérios de avaliação
- Três telas ligadas, com troca de cena.
- Autoload usado para o que passa entre cenas.
- Recorde salvo e lido de arquivo.
Checklist de conclusão
Extensão
Compare com o Cajueiral (Aula 6.5): lá o progresso ficava no armazenamento do navegador; aqui, num arquivo. O que acontece com cada um quando se troca de computador?