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 8 · Aula 8.6 · Telas, Autoload e recorde salvo

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

Objetivos de aprendizagem

  1. Montar telas com nós de interface (Control, Label, TextureRect) e um placar por cima do jogo (CanvasLayer).
  2. Trocar de cena com get_tree().change_scene_to_file().
  3. Guardar dados que passam de uma cena para outra num Autoload.
  4. Salvar e carregar o recorde num arquivo (FileAccess, pasta user://).
  5. Esperar 1 segundo com await antes 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

PerguntaOnde guardar
pontos da partida que a tela de fim precisa mostrarAutoload (Global.pontos)
recorde que deve valer amanhãarquivo em user://
vidas, que só importam durante a partidavariável no script do jogo

Tutorial passo a passo

Parte A. Autoload (90 min)

  1. No Sementes, abra Configurações do Projeto... → Globais → Autoload e veja Global com res://scripts/global.gd (captura abaixo).
  2. Leia global.gd. Por que pontos está aqui e vidas está em jogo.gd?
  3. No seu projeto, crie global.gd com var pontos := 0 e registre como Autoload com Selecionar Script/Cena. Confira na coluna Nome que ficou Global. (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)

  1. Cena inicio.tscn com raiz Control, um TextureRect de fundo e dois Label (título e instruções).
  2. Script inicio.gd: na ação comecar (Espaço e Enter, no Mapa de Entrada) ou num clique, troca para jogo.tscn.
  3. Cena fim.tscn igual, com um Label chamado Resultado.
  4. No jogo, quando acabar o tempo ou as vidas, chame terminar().
  5. Defina inicio.tscn como cena principal (Aula 8.1) e jogue do começo ao fim.

Parte C. Recorde salvo (120 min)

  1. Acrescente recorde, salvar_recorde(), carregar_recorde() e terminar_partida() no global.gd.
  2. Jogue, feche o jogo, abra de novo: o recorde continua?
  3. 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)

  1. 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 await e a variável pode_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

ItemNome na tela
AutoloadConfiguraçõ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 principalConfigurações do Projeto... → Geral → Application → Run → Main Scene
nova cena de interfaceCriar 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_var e get_var guardam 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.
  • \n no 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_deferred porque 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

SintomaCausaSolução
Identifier "Global" not declaredAutoload não registrado, ou com outro nomeregistrar na aba Globais com o nome Global
pontos zeram na tela de fimpontos guardados no script do jogoguardar no Autoload
recorde não fica salvosalvou em res://usar user://
a tela de fim some na horatecla ainda apertada no fimesperar 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?