DEV Community

Alair Joao Tavares
Alair Joao Tavares

Posted on • Originally published at activi.dev

Dominando a Física de TileMaps no Godot 4: Construindo Plataformas Sólidas e Unidirecionais com GDScript

Em qualquer jogo de plataforma 2D, a interação do jogador com o mundo é a base da experiência. Um pulo que falha, uma parede que não bloqueia ou uma plataforma que te deixa cair sem motivo pode quebrar a imersão e frustrar o jogador. No Godot Engine, o nó TileMap é uma ferramenta incrivelmente poderosa para construir níveis de forma rápida e eficiente, mas configurar sua física de maneira robusta exige atenção aos detalhes. Como podemos garantir que nossas plataformas sejam sólidas como rocha e que nossas plataformas "atravessáveis" funcionem perfeitamente?

Este artigo é um guia completo para dominar a física dos TileMaps no Godot 4. Vamos mergulhar na configuração de TileSets, desenhar formas de colisão precisas para diferentes tipos de terreno e, o mais importante, explorar como o GDScript pode nos ajudar a refinar e automatizar esse processo. Ao final, você terá o conhecimento necessário para criar interações de plataforma pixel-perfect, evitando as armadilhas comuns do desenvolvimento de jogos 2D.

1. A Base de Tudo: Configurando o TileSet e as Camadas de Física

Antes de podermos definir como os objetos colidem, precisamos estabelecer o terreno. No Godot, isso começa com a relação entre dois nós principais: TileMap e TileSet. O TileMap é o nó que você adiciona à sua cena para "pintar" os níveis, enquanto o TileSet é o recurso que contém os tiles (as imagens) e todas as suas propriedades, incluindo a física.

O primeiro passo é criar um recurso TileSet. Com seu nó TileMap selecionado, vá até o Inspetor e, na propriedade Tile Set, clique em [vazio] e selecione Novo TileSet.

Criando um novo TileSet no inspetor do Godot

Ao clicar no novo recurso TileSet, o painel TileSet aparecerá na parte inferior da interface. Aqui, você pode arrastar sua imagem de tilesheet (por exemplo, tiles.png) para a coluna da esquerda para criar um novo atlas. Após a configuração inicial do tamanho dos tiles, o próximo passo crucial é configurar as Camadas de Física (Physics Layers).

As camadas de física dentro de um TileSet permitem que você defina diferentes comportamentos de colisão para diferentes grupos de tiles, tudo dentro do mesmo recurso. Por exemplo, você pode ter uma camada para terreno sólido, outra para plataformas que só podem ser atravessadas por baixo e até uma para áreas de dano, como espinhos.

Para adicionar uma camada, vá para a aba TileSet no Inspetor, expanda a seção Physics Layers e clique em Add Element. É uma boa prática nomear suas camadas de forma descritiva. Vamos criar duas:

  1. terreno_solido: Para paredes e chão.
  2. plataformas_unidirecionais: Para plataformas que o jogador pode pular por baixo.

Cada camada de física que você cria no TileSet corresponde a uma camada de colisão 2D padrão do Godot. Isso significa que você pode configurar a interação entre seu jogador (CharacterBody2D) e o TileMap usando as propriedades collision_layer e collision_mask.

Configurando as Camadas de Física no TileSet

Com nossas camadas prontas, estamos preparados para dar forma ao nosso mundo.

2. Construindo o Chão: Formas de Colisão Sólidas

Vamos começar com o tipo mais simples de colisão: plataformas sólidas. São as paredes, o chão e os tetos que formam os limites do seu nível.

No editor de TileSet, na parte inferior, selecione a aba Select. Escolha um tile do seu atlas que deva ser sólido, como um bloco de grama ou pedra. Em seguida, mude para a aba Paint à direita.

No painel Paint, selecione a sub-aba Physics e certifique-se de que sua camada terreno_solido esteja selecionada. Agora você tem as ferramentas para desenhar a forma da colisão. Para um bloco quadrado padrão, a ferramenta de polígono é ideal. Clique nos quatro cantos do seu tile para desenhar um retângulo que cubra toda a sua área. Ao fechar o polígono (clicando no primeiro ponto novamente), uma forma de colisão azul aparecerá sobre o tile.

Desenhando uma forma de colisão retangular em um tile

Qualquer tile que você pintar em seu TileMap agora terá essa forma de colisão. Para que seu jogador interaja com ele, o script do jogador (CharacterBody2D) precisa estar configurado para colidir com a camada correspondente. Por padrão, um CharacterBody2D colide com a camada 1, e o TileMap também coloca sua primeira camada de física na camada de colisão 1. Se suas configurações forem padrão, tudo deve funcionar imediatamente.

Aqui está um exemplo básico de script de jogador que irá interagir com essas colisões sólidas:

# player.gd
extends CharacterBody2D

const SPEED = 250.0
const JUMP_VELOCITY = -450.0

# Obter a gravidade das configurações do projeto para mantê-la consistente.
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")

func _physics_process(delta):
    # Adicionar gravidade ao jogador.
    if not is_on_floor():
        velocity.y += gravity * delta

    # Processar o pulo.
    if Input.is_action_just_pressed("ui_accept") and is_on_floor():
        velocity.y = JUMP_VELOCITY

    # Obter a direção da entrada (esquerda/direita).
    var direction = Input.get_axis("ui_left", "ui_right")
    if direction:
        velocity.x = direction * SPEED
    else:
        velocity.x = move_toward(velocity.x, 0, SPEED)

    move_and_slide()

Enter fullscreen mode Exit fullscreen mode

Com este script e a forma de colisão sólida configurada, seu jogador agora pode correr e pular sobre o terreno que você criou, sem atravessar o chão ou as paredes.

3. A Mágica das Plataformas Unidirecionais (One-Way)

Plataformas unidirecionais, ou one-way platforms, são um elemento clássico de jogos de plataforma. Elas permitem que o jogador pule através delas por baixo, mas agem como um chão sólido quando o jogador está em cima. Configurá-las no Godot é surpreendentemente simples.

Volte para o editor de TileSet. Selecione o tile que você quer usar como plataforma unidirecional. No painel Paint, certifique-se de selecionar sua camada de física plataformas_unidirecionais. Em vez de desenhar um polígono que cubra todo o tile, desenhe apenas uma linha ou um retângulo muito fino na borda superior do tile. Esta será a única superfície com a qual o jogador poderá colidir.

Desenhando uma linha de colisão no topo de um tile

Agora vem o passo crucial. Com o polígono que você acabou de desenhar ainda selecionado (ele deve estar destacado), procure no Inspetor (à direita) pela seção Physics Layer 1 (ou qualquer que seja o índice da sua camada de plataformas). Dentro dela, você encontrará uma propriedade booleana chamada One Way. Marque esta caixa.

É isso! Esta simples caixa de seleção instrui o motor de física a tratar qualquer colisão com esta forma como unidirecional. O Godot é inteligente o suficiente para permitir que corpos passem por ela se sua velocidade estiver apontando para cima em relação à superfície da colisão, e colidir se estiverem se movendo para baixo.

Se o seu jogador estiver caindo rápido demais e atravessando a plataforma, você pode ajustar a propriedade one_way_collision_margin do seu nó CharacterBody2D. Um valor maior (por exemplo, 5.0) torna a detecção mais robusta, mas o padrão geralmente funciona bem.

4. Ajustes Finos e Dicas Práticas com GDScript

O editor do Godot é fantástico para configurar a maioria das colisões, mas às vezes você pode precisar de um controle mais granular ou pode encontrar peculiaridades específicas da versão do motor. Recentemente, durante o desenvolvimento de um projeto, deparei-me com uma mudança sutil, mas importante, do GDScript 3 para o 4 que afeta a definição de formas de colisão programaticamente.

Em projetos mais antigos ou em alguns tutoriais, você pode ver formas de colisão, que são do tipo PackedVector2Array, sendo definidas como constantes (const). No entanto, o GDScript 4 não permite mais que PackedVector2Array seja uma constante. Ele deve ser definido como uma variável (var). Isso é importante se você estiver escrevendo scripts de ferramentas (@tool) para automatizar a configuração do seu TileSet ou modificá-lo em tempo de execução.

Vamos ver um exemplo prático de um script @tool que define formas de colisão para tiles específicos. Este script pode ser anexado a um nó na sua cena principal para configurar um TileSet de forma programática.

# tileset_configurator.gd
@tool
extends Node

@export var target_tile_set: TileSet

# Um botão para acionar a lógica no editor.
@export var configure_now: bool = false:
    set(value):
        if value:
            setup_tile_collisions()

func setup_tile_collisions():
    if not target_tile_set:
        print("ERRO: Nenhum TileSet de alvo foi definido.")
        return

    # No GDScript 4, PackedVector2Array DEVE ser 'var', não 'const'.
    var full_collision_shape: PackedVector2Array = [
        Vector2(0, 0), Vector2(16, 0), Vector2(16, 16), Vector2(0, 16)
    ]

    var top_collision_shape: PackedVector2Array = [
        Vector2(0, 1), Vector2(16, 1) # Um pouco para baixo para melhor contato
    ]

    # --- Configurando um tile sólido ---
    # Parâmetros: source_id, atlas_coords, alternative_id
    var solid_tile_coords = Vector2i(0, 4) # Ex: tile na coluna 0, linha 4
    # Obter os dados do tile para modificação
    var solid_tile_data = target_tile_set.get_tile_data(0, solid_tile_coords, 0)

    if solid_tile_data:
        # Limpar polígonos antigos na camada 0 (terreno_solido)
        solid_tile_data.clear_collision_polygons(0)
        # Adicionar um novo polígono à camada 0
        solid_tile_data.add_collision_polygon(0)
        solid_tile_data.set_collision_polygon_points(0, 0, full_collision_shape)
        print(f"Colisão sólida configurada para o tile em {solid_tile_coords}")

    # --- Configurando um tile unidirecional ---
    var oneway_tile_coords = Vector2i(1, 4) # Ex: tile na coluna 1, linha 4
    var oneway_tile_data = target_tile_set.get_tile_data(0, oneway_tile_coords, 0)

    if oneway_tile_data:
        # Usando a camada de física 1 (plataformas_unidirecionais)
        oneway_tile_data.clear_collision_polygons(1)
        oneway_tile_data.add_collision_polygon(1)
        oneway_tile_data.set_collision_polygon_points(1, 0, top_collision_shape)
        # A propriedade 'one_way' é definida por polígono!
        oneway_tile_data.set_collision_polygon_one_way(1, 0, true)
        print(f"Colisão unidirecional configurada para o tile em {oneway_tile_coords}")

Enter fullscreen mode Exit fullscreen mode

Este script não apenas demonstra a sintaxe correta para PackedVector2Array, mas também revela o poder de modificar recursos TileSet via código. Você pode usá-lo para gerar colisões para centenas de tiles, garantindo consistência e economizando um tempo de desenvolvimento precioso.

Conclusão

Configurar a física de TileMap no Godot 4 é um processo de camadas, tanto literal quanto figurativamente. Começa com uma estrutura sólida de Camadas de Física no seu recurso TileSet e continua com o desenho cuidadoso de polígonos de colisão para cada tipo de tile. Ao dominar a distinção entre colisões sólidas e as configurações One Way, você desbloqueia a capacidade de criar níveis dinâmicos e intuitivos.

Os principais pontos a serem lembrados são:

  • Use Camadas de Física no TileSet para organizar diferentes comportamentos de colisão.
  • Para plataformas sólidas, desenhe um polígono que cubra toda a área do tile.
  • Para plataformas unidirecionais, desenhe uma forma fina na superfície superior e ative a propriedade One Way para essa forma específica.
  • Ao definir formas de colisão em GDScript 4, lembre-se de usar var em vez de const para PackedVector2Array.

Com essas técnicas em seu arsenal, você está bem equipado para construir mundos 2D confiáveis e divertidos de explorar. Agora vá em frente e crie plataformas perfeitas!

Top comments (0)