O que é TileMap e por que usar em fases 2D
TileMap é um nó pensado para construir cenários 2D a partir de “peças” (tiles) colocadas em uma grade. Em vez de desenhar um cenário inteiro como uma única imagem, você monta o nível combinando tiles reutilizáveis. Isso facilita editar, expandir e manter o cenário, além de permitir colisão por tile (o chão e paredes “sólidos” vêm do próprio tileset).
Na prática, você vai trabalhar com três elementos: TileSet (o conjunto de tiles e suas regras), TileMap (onde você pinta os tiles) e colisões por tile (formas de colisão associadas a cada tile sólido).
Preparando o TileSet (tiles + colisões)
1) Criar/importar a textura do tileset
Você pode usar uma imagem com vários tiles (spritesheet) ou tiles separados. Para um primeiro cenário, um spritesheet é comum: uma imagem com blocos do mesmo tamanho (ex.: 16x16, 32x32).
- Importe a imagem do tileset para o projeto.
- Confirme o tamanho do tile (ex.: 32x32). Isso precisa ser consistente com o que você vai configurar no TileSet.
2) Criar um TileSet e fatiar os tiles
No Godot 4, você cria um recurso TileSet e define uma ou mais fontes de tiles (geralmente uma Atlas Source para spritesheet).
- Crie um nó
TileMapna sua cena de fase (ou em uma cena separada). - No Inspector do TileMap, crie/atribua um TileSet.
- Abra o editor de TileSet e adicione uma fonte do tipo Atlas apontando para a textura.
- Defina o tamanho do tile (ex.: 32x32) e gere a grade de recortes.
3) Adicionar colisão por tile (chão, parede, plataforma)
Para cada tile que deve ser sólido, você define uma forma de colisão no TileSet. Assim, ao “pintar” o tile no TileMap, a colisão vem junto.
- Ouça o áudio com a tela desligada
- Ganhe Certificado após a conclusão
- + de 5000 cursos para você explorar!
Baixar o aplicativo
- No editor do TileSet, selecione um tile (ex.: bloco de chão).
- Na aba de colisão, adicione um shape (normalmente um retângulo ocupando o tile inteiro).
- Repita para tiles de parede, blocos, etc.
Plataformas (one-way): para tiles que funcionam como plataforma (o jogador sobe por baixo e só colide ao cair por cima), marque a colisão como one-way (colisão unidirecional). Isso é configurado no próprio shape de colisão do tile, no TileSet.
- Crie um tile de plataforma (ex.: uma “tábua”).
- Adicione um shape fino (uma faixa horizontal na parte superior do tile) para evitar “bater a cabeça” em um retângulo grande.
- Ative one-way e ajuste a margem/threshold se necessário para evitar atravessar ao descer.
Organização do cenário: camadas visuais vs camadas de colisão
Um erro comum é misturar tudo em uma única camada: decoração, fundo, chão sólido, plataformas e detalhes. Isso torna o nível difícil de editar e aumenta a chance de colisões indesejadas.
Estratégia recomendada (editável e limpa)
- Camada Visual (decoração): tiles sem colisão (grama decorativa, detalhes, fundo).
- Camada de Colisão (jogável): tiles com colisão (chão, paredes, plataformas).
- Camada de “foreground” (opcional): elementos que ficam na frente do player, sem colisão.
No TileMap, use Layers (camadas do próprio TileMap) ou use dois TileMaps separados (um para visual e outro para colisão). As duas abordagens funcionam; para iniciantes, dois TileMaps deixam mais explícito o que é jogável.
Boas práticas para manter o nível fácil de editar
- Nomeie claramente:
TileMap_Collision,TileMap_Decor. - Trave (lock) a camada de colisão quando estiver decorando, e vice-versa, para evitar pintar no lugar errado.
- Evite colisão em tiles decorativos (folhas, pedras pequenas) para não “prender” o player.
- Use plataformas one-way apenas onde fizer sentido; excesso de one-way pode gerar comportamento confuso.
Passo a passo: montando um cenário simples jogável
1) Criar a cena da fase
Crie uma nova cena para a fase (ex.: Level01.tscn) com um nó raiz do tipo Node2D (ou Marker2D não; prefira Node2D como raiz).
Estrutura sugerida:
Level01 (Node2D) TileMap_Collision (TileMap) TileMap_Decor (TileMap) PlayerSpawn (Marker2D) CameraRig (Node2D) Camera2D (Camera2D) Limits (Node2D) KillZone (Area2D) CollisionShape2D LevelBounds (StaticBody2D) CollisionShape2DObservação: você pode adaptar aos nós que já tem no projeto (por exemplo, se o player já possui Camera2D). Aqui vamos usar uma câmera provisória para o loop de teste.
2) Configurar o TileMap de colisão
- Adicione
TileMap_Collision. - Atribua o TileSet com colisões configuradas.
- Pinte o chão e algumas plataformas/paredes para formar um percurso simples: uma área inicial plana, um degrau, uma plataforma one-way, um corredor, etc.
Dica de design: comece com um “caminho crítico” simples (do ponto A ao B) antes de decorar.
3) Configurar o TileMap de decoração
- Adicione
TileMap_Decorusando o mesmo TileSet (ou outro TileSet só decorativo). - Pinte grama, bordas, detalhes e fundo.
- Garanta que esses tiles não tenham colisão no TileSet (ou use tiles sem shapes).
Pontos de spawn e áreas de limite
1) Ponto de spawn do player
Crie um Marker2D chamado PlayerSpawn e posicione onde o player deve aparecer ao iniciar a fase.
Se você já tem uma cena de Player pronta, a fase pode instanciá-la e posicioná-la no spawn. Exemplo de script simples no nó raiz da fase:
extends Node2D@export var player_scene: PackedScenevar player: Nodefunc _ready(): if player_scene == null: return player = player_scene.instantiate() add_child(player) player.global_position = $PlayerSpawn.global_positionSe o seu Player for CharacterBody2D, isso funciona bem. Se você já instancia o player por outro sistema (ex.: GameManager), use o PlayerSpawn apenas como referência de posição.
2) Limites do nível (paredes invisíveis e “queda”)
Dois limites úteis para um loop de teste:
- KillZone: uma área abaixo do cenário que detecta quando o player caiu (para resetar no spawn).
- LevelBounds: colisores invisíveis nas laterais (para impedir sair do mapa) e/ou um teto.
KillZone com Area2D
Crie KillZone (Area2D) com CollisionShape2D (um retângulo largo) posicionado abaixo do chão. Conecte o sinal body_entered e, quando o player entrar, reposicione no spawn.
extends Area2D@export var spawn_path: NodePathfunc _on_body_entered(body): if not body.is_in_group("player"): return var spawn := get_node_or_null(spawn_path) if spawn == null: return body.global_position = spawn.global_position # opcional: zerar velocidade se seu player expõe issoPara isso funcionar, adicione o player ao grupo player (no Inspector do nó do player, em Groups).
LevelBounds com StaticBody2D
Crie um StaticBody2D chamado LevelBounds e adicione um ou mais CollisionShape2D (retângulos) nas laterais do mapa. Isso evita que o player saia do cenário sem precisar “fechar” tudo com tiles sólidos.
- Um retângulo alto na esquerda.
- Um retângulo alto na direita.
- (Opcional) um teto se você tiver pulos altos.
Regras básicas para plataformas (one-way) e dicas de uso
Quando usar one-way
- Plataformas suspensas onde o player deve atravessar por baixo e aterrissar por cima.
- Passagens verticais (subir e cair) sem bloquear o pulo.
Como evitar problemas comuns
- Shape fino: use colisão apenas na parte superior do tile de plataforma (uma faixa), reduzindo colisões laterais estranhas.
- Não misture one-way com paredes: evite colocar tiles one-way encostados em paredes sólidas sem um desenho claro; isso pode criar “quinas” difíceis.
- Teste descida: se seu jogo tiver “descer da plataforma” (ex.: apertar para baixo + pulo), você vai precisar de lógica no player para desabilitar colisão temporariamente. Se ainda não implementou isso, mantenha o design sem exigir essa mecânica.
Loop de teste jogável: atravessar o nível com colisões e câmera provisória
1) Câmera provisória seguindo o player
Se o seu player ainda não tem câmera, crie um Camera2D na cena da fase e faça ela seguir o player via script simples. Estrutura:
CameraRig (Node2D)comCamera2Dcomo filho.- Ative
Currentna Camera2D.
Script no CameraRig:
extends Node2D@export var target_path: NodePath@export var follow_speed := 12.0var target: Node2Dfunc _ready(): target = get_node_or_null(target_path)func _process(delta): if target == null: return global_position = global_position.lerp(target.global_position, 1.0 - pow(0.001, follow_speed * delta))Depois, aponte target_path para o nó do player instanciado (se você instancia no _ready, pode setar isso via código logo após criar o player):
$CameraRig.target_path = player.get_path()2) Limites da câmera (opcional, mas recomendado)
Para evitar mostrar “fora do mapa”, configure limites na Camera2D. Você pode definir manualmente valores de limit_left, limit_right, limit_top, limit_bottom com base no tamanho do seu nível (em pixels). Para um teste rápido, comece sem limites e adicione depois.
3) Checklist do teste jogável
- O player nasce no
PlayerSpawn. - O chão (tiles sólidos) impede atravessar.
- Paredes bloqueiam lateralmente.
- Plataformas one-way permitem atravessar por baixo e aterrissar por cima.
- Ao cair no
KillZone, o player volta ao spawn. - A câmera segue o player de forma estável.
4) Ajustes rápidos quando algo não funciona
| Sintoma | Causa provável | Correção |
|---|---|---|
| Player atravessa o chão | Tile sem shape de colisão no TileSet ou TileMap errado | Confirme shapes no TileSet e se você pintou no TileMap_Collision |
| Colisão “invisível” em decoração | Tile decorativo com shape | Remova shape do tile decorativo ou use tiles sem colisão |
| Não consigo pular através da plataforma | Plataforma não está one-way ou shape grande demais | Ative one-way e use shape fino no topo |
| Camera tremendo | Follow muito agressivo ou target errado | Reduza follow_speed e confirme target_path |
| Reset no spawn mas player continua caindo | Spawn dentro de colisão ou abaixo do chão | Reposicione o PlayerSpawn acima do chão |