O que é um sistema de fases (levels) com spawns e progressão
Um sistema de fases organiza o jogo em layouts separados (uma fase por Layout) e define regras consistentes para: onde o jogador nasce (spawn), onde ele reaparece após falhar (checkpoint), quando a fase termina (condição de vitória) e como avançar para a próxima fase (transição). A ideia central é reutilizar a mesma lógica em todas as fases, mudando apenas “marcadores” posicionados no cenário (instâncias invisíveis como SpawnPoint e Exit).
Neste capítulo, você vai montar uma estrutura reutilizável baseada em: (1) objetos marcadores no Layout, (2) variáveis globais para controlar a fase atual e o último checkpoint, (3) eventos que reposicionam e resetam entidades ao reiniciar, e (4) transição automática para o próximo Layout mantendo HUD e variáveis coerentes.
Estrutura recomendada (objetos marcadores e variáveis)
Objetos marcadores (invisíveis)
- SpawnPoint: sprite simples (ex.: um quadrado), com
Visible = falseno início do layout. Pode ter uma Instance variableid(número) para diferenciar spawns. - Checkpoint (opcional, mas recomendado): marcador invisível com
ide/ouactivated(boolean). - Exit: marcador invisível que representa a saída da fase. Pode ter
nextLevel(texto) ounextIndex(número) para decidir qual fase carregar.
Variáveis globais (controle de progressão)
Crie variáveis globais para manter o estado entre layouts (HUD e progressão):
gLevelIndex(número): índice da fase atual (ex.: 1, 2, 3...).gCheckpointId(número): último checkpoint ativado na fase atual. Use0para “nenhum checkpoint” (volta ao spawn inicial).gLives,gScore, etc.: já devem existir do seu sistema de HUD; aqui apenas garantimos que não sejam resetadas ao trocar de fase.
Variáveis locais por Layout (opcional)
Se quiser, use uma variável no Layout para definir o “próximo layout” sem depender de nomes fixos:
LevelNext(texto): nome do próximo Layout (ex.:Level2).
Passo a passo: criando spawns e saída reutilizáveis
1) Criar e posicionar marcadores no Layout
Em cada fase (Layout), posicione:
- Ouça o áudio com a tela desligada
- Ganhe Certificado após a conclusão
- + de 5000 cursos para você explorar!
Baixar o aplicativo
- 1
SpawnPointcomid = 0(spawn inicial). - 0 ou mais
Checkpointcomid = 1, 2, 3...(em pontos seguros do mapa). - 1
Exitno final da fase (na porta, bandeira, elevador, etc.).
Dica prática: deixe os marcadores em uma camada “Markers” e mantenha essa camada bloqueada para não mover sem querer.
2) Evento de spawn do jogador ao iniciar a fase
Objetivo: quando o Layout começar, o jogador deve aparecer no último checkpoint (se existir) ou no spawn inicial.
Crie um grupo de eventos chamado Spawn & Reset no Event Sheet da fase (ou em um Event Sheet compartilhado, se você já usa um sistema de folhas comuns).
Event: On start of layout (System)Dentro dele, faça a lógica em duas partes:
- Se houver checkpoint salvo (
gCheckpointId > 0): encontre oCheckpointcom aqueleide posicione o Player nele. - Se não houver checkpoint: use o
SpawnPointcomid = 0.
Em Construct (por eventos), isso fica assim (em termos de intenção):
System: On start of layoutSystem: If gCheckpointId > 0Checkpoint: Pick Checkpoint where id = gCheckpointIdPlayer: Set position to (Checkpoint.X, Checkpoint.Y)
System: ElseSpawnPoint: Pick SpawnPoint where id = 0Player: Set position to (SpawnPoint.X, SpawnPoint.Y)
Observação importante: se você usa câmera seguindo o jogador, garanta que a câmera atualize após posicionar o Player (normalmente acontece automaticamente, mas se você tiver lógica de scroll customizada, rode-a após o spawn).
3) Checkpoint simples (ativação e salvamento)
Objetivo: ao tocar no checkpoint, salvar o id dele em gCheckpointId e (opcional) dar feedback visual/sonoro.
Event: Player on collision with CheckpointAções recomendadas:
System: Set gCheckpointId = Checkpoint.idCheckpoint: Set activated = true(se usar)- Opcional: desativar colisão do checkpoint após ativar para evitar reativação constante (ex.: mudar para uma animação “ativo” e/ou usar uma condição
Checkpoint.activated = falseantes de salvar).
Exemplo de regra para evitar reativação:
Player on collision with CheckpointANDCheckpoint.activated = false- → salvar
gCheckpointId, setaractivated = true.
4) Condição de vitória: alcançar a saída (Exit)
Objetivo: quando o jogador encostar na Exit, finalizar a fase e carregar a próxima.
Você pode fazer a transição de duas formas:
- Por índice global:
gLevelIndexincrementa e você decide qual Layout abrir. - Por variável no Exit: cada Exit sabe qual é o próximo Layout (mais flexível).
Opção A: Exit com variável nextLevel (texto)
No objeto Exit, crie a instance variable nextLevel (texto). Em cada fase, configure o valor (ex.: em Level1, nextLevel = "Level2").
Event: Player on collision with ExitSystem: Set gCheckpointId = 0(novo level começa sem checkpoint)System: Add 1 to gLevelIndex(opcional, para HUD/estatísticas)System: Go to layout (Exit.nextLevel)
Opção B: Progressão por lista fixa (controle central)
Se você prefere controlar a ordem em um único lugar, crie uma lógica do tipo:
- Se
gLevelIndex = 1→ ir paraLevel2 - Se
gLevelIndex = 2→ ir paraLevel3
Isso é simples, mas menos escalável. A opção A costuma ser mais prática para protótipos com múltiplos caminhos.
Reset de entidades ao reiniciar (sem bagunçar HUD/global)
Quando o jogador morre ou você reinicia a fase, é comum precisar “limpar” inimigos, projéteis, itens temporários e estados de comportamento. O objetivo aqui é: reiniciar o Layout mantendo variáveis globais (vidas, score, etc.) e reaparecer no checkpoint correto.
Estratégia 1 (recomendada): reiniciar o Layout e reconstruir tudo
Se os inimigos/itens são colocados no Layout (não gerados proceduralmente), a forma mais limpa é:
- Ao morrer: decrementar vida (global) e
Restart layout. - No
On start of layout, reposicionar o Player no spawn/checkpoint (como já fizemos).
Isso automaticamente recria instâncias do Layout no estado inicial, o que “reseta” inimigos e itens colocados manualmente. O que precisa de atenção é o que foi criado dinamicamente durante o gameplay (ex.: projéteis, partículas persistentes, drops gerados por eventos).
Estratégia 2: limpeza manual de instâncias dinâmicas
Crie uma família ou lista de objetos “temporários” (ex.: Bullet, EnemyProjectile, DropTemp) e destrua ao reiniciar.
Exemplo de ações ao reiniciar (antes do restart, ou no start do layout):
Destroy BulletDestroy EnemyProjectileDestroy FloatingText(se você usa textos flutuantes como feedback)
Se você usa partículas, normalmente elas se encerram sozinhas, mas se tiver emissor persistente, desligue-o no reset.
Reset de estado do Player (evitar “herdar” condições ruins)
Além de reposicionar, é comum resetar estados do Player:
- Zerar velocidade (se usa behaviors com velocidade): setar vetor/velocidade para 0.
- Resetar flags como “invencível”, “atacando”, “stun”.
- Garantir animação padrão (idle) ao spawn.
Faça isso no mesmo bloco do spawn (após posicionar).
Manter HUD e variáveis globais coerentes entre fases
Para o HUD não “sumir” ou duplicar ao trocar de Layout, use uma destas abordagens:
- HUD em um Layout separado persistente (se você já estruturou assim): ao trocar de fase, não recrie o HUD; apenas atualize textos/barras com base nas variáveis globais.
- HUD no próprio Layout: ao entrar em cada fase, o HUD é recriado, mas lê as variáveis globais (
gLives,gScore) e exibe corretamente. Evite resetar essas variáveis noOn start of layoutdas fases.
Regra prática: variáveis globais só são inicializadas no início de uma “run” (ex.: ao apertar “Novo Jogo”), não no início de cada fase.
Padrão de eventos sugerido (organização)
Para facilitar manutenção, separe em grupos:
- Level Init:
On start of layout, spawn, reset de estados. - Checkpoint: ativação, feedback, salvamento.
- Win/Exit: colisão com Exit, transição, limpeza de checkpoint.
- Restart: morte, restart, limpeza de temporários.
Mesmo que cada fase tenha seu Event Sheet, tente manter os nomes e a ordem dos grupos iguais em todas as fases.
Exercício prático: duas fases com layouts diferentes e progressão
Objetivo do exercício
- Criar Level1 e Level2 com layouts diferentes.
- Configurar SpawnPoint, Checkpoint e Exit em cada uma.
- Ao alcançar a saída do Level1, carregar Level2.
- Manter HUD e variáveis globais (vidas, score) consistentes.
- Ao morrer, reiniciar a fase e reaparecer no último checkpoint.
Parte A — Montagem do Level1
- Crie/abra o Layout
Level1. - Posicione
SpawnPointcomid = 0no início. - Posicione um
Checkpointno meio da fase comid = 1. - Posicione
Exitno final e definanextLevel = "Level2".
Parte B — Montagem do Level2
- Crie/abra o Layout
Level2com um layout visual diferente (plataformas em outra altura, outro caminho, mais inimigos, etc.). - Posicione
SpawnPointcomid = 0no início do Level2. - Opcional: adicione dois checkpoints (
id = 1eid = 2). - Posicione
Exitno final. Se ainda não houver Level3, você pode apontar para um layout de vitória ou menu (dependendo do seu fluxo), mas mantenha a mesma lógica de transição.
Parte C — Eventos essenciais (copiar para as duas fases)
Em Level1 e Level2, garanta que existam estes eventos:
| Categoria | Evento | Ação principal |
|---|---|---|
| Spawn | On start of layout | Se gCheckpointId > 0 spawn no Checkpoint; senão spawn no SpawnPoint id 0; resetar estado do Player |
| Checkpoint | Player colide com Checkpoint (e activated=false) | gCheckpointId = Checkpoint.id; marcar activated |
| Saída | Player colide com Exit | gCheckpointId = 0; (opcional) gLevelIndex++; Go to layout (Exit.nextLevel) |
| Restart | Quando morrer (condição do seu jogo) | Decrementar vida (global) e Restart layout; limpar temporários se necessário |
Parte D — Checklist de validação
- Ao iniciar Level1, o Player aparece no SpawnPoint id 0.
- Ao tocar no Checkpoint id 1 e morrer, o restart faz o Player reaparecer no checkpoint (não no início).
- Ao tocar no Exit do Level1, o jogo carrega Level2 e o HUD mantém vidas/score.
- Ao entrar no Level2,
gCheckpointIdestá em 0 (novo level), então o Player nasce no SpawnPoint do Level2. - Projéteis/objetos temporários não “vazam” após restart (se vazarem, adicione destruição no reset).