Como Criar um Sistema de Estradas automático para City Builders na Godot
Todo jogo do gênero City Builder precisa de um sistema de estradas eficiente. Afinal, as estradas são a base da movimentação da cidade, conectando edifícios, recursos, veículos e futuras mecânicas de gameplay.
Mas existe um problema: ninguém quer construir e corrigir estradas manualmente, célula por célula, principalmente em mapas grandes. Pensando nisso, desenvolvi um sistema de estradas automático na Godot que identifica conexões, corrige as peças necessárias e cria uma base sólida para implementar recursos como tráfego, transporte de recursos e expansão urbana.
Neste artigo vou explicar como esse sistema funciona e a lógica utilizada para tornar tudo possível.
O Road Builder
A primeira etapa do sistema foi criar o que chamei de Road Builder.
Sua principal função é permitir que o jogador posicione estradas normalmente enquanto o sistema se encarrega de corrigir automaticamente o modelo visual utilizado.
Na prática, quando uma nova estrada é construída, o sistema analisa os seus vizinhos e determina qual peça deve ser exibida:
- Fim de estrada (Dead End)
- Estrada reta
- Curva
- Cruzamento em T
- Cruzamento completo
Além disso, ele ajusta automaticamente a rotação correta da peça.
O resultado é um sistema muito mais intuitivo para o jogador, que não precisa escolher manualmente qual tipo de estrada deseja posicionar.
O Coração do Sistema: Verificação de Vizinhos
As funções responsáveis por toda a lógica são:
check_road_neighbors()road_fix_base()
Sempre que uma nova estrada é posicionada, o sistema precisa responder a uma pergunta simples:
Quais são os vizinhos dessa célula?
Para isso, verificamos as quatro direções principais:
- Back (trás)
- Front (frente)
- Left (esquerda)
- Right (direita)
Dependendo das conexões encontradas, uma configuração diferente de estrada será utilizada.
Mas como armazenar todas essas combinações de forma eficiente?
Utilizando Flags Binárias
A Godot oferece um recurso extremamente útil chamado @export_flags.
Esse recurso permite representar vários estados booleanos dentro de uma única variável inteira.
No sistema de estradas, cada direção recebe um valor específico:
| Direção | Valor |
|---|---|
| Back | 1 |
| Front | 2 |
| Left | 4 |
| Right | 8 |
Com isso, podemos combinar os valores para representar qualquer configuração de vizinhos.
Exemplo 1: Estrada apenas atrás
Back = 1
Front = 0
Left = 0
Right = 0Valor final:
0001 = 1Exemplo 2: Estradas na frente e atrás
Back = 1
Front = 2Valor final:
0011 = 3Exemplo 3: Estradas em todas as direções
Back = 1
Front = 2
Left = 4
Right = 8Valor final:
1111 = 15Como temos quatro direções possíveis, podemos gerar:
2⁴ = 16 combinações
Ou seja, valores de 0 a 15.
A Função check_road_neighbors()
A função check_road_neighbors() é responsável por analisar a célula atual e seus vizinhos.
Para cada direção, o sistema verifica se existe uma estrada.
Caso exista, o valor correspondente é somado ao resultado final:
status | = 1 # Back
status | = 2 # Front
status | = 4 # Left
status | = 8 # RightAo final da verificação, a função retorna um valor entre 0 e 15.
Esse valor representa exatamente a configuração de conexões daquela célula.
Convertendo o Valor em Estradas
Depois que o sistema identifica a configuração dos vizinhos, entra em ação a função:
func road_fix_base()Primeiro ela verifica se a estrutura analisada realmente é uma estrada.
Se não for, a execução é interrompida.
Caso seja uma estrada, a função consulta o valor retornado por check_road_neighbors().
Em seguida, um bloco match determina qual modelo deve ser construído:
match structure_neighbors_is_road_status:
0:
build_parking()
5:
build_corner()Cada valor representa uma configuração específica de conexões.
Além disso, a função também define a rotação correta da peça para garantir o encaixe perfeito entre os segmentos.
Corrigindo Toda a Rede de Estradas
Quando uma nova estrada é posicionada, não basta corrigir apenas ela.
Os seus vizinhos também podem precisar de atualização.
Por exemplo:
Antes:
Dead EndDepois de adicionar uma nova estrada:
Estrada RetaPor isso o sistema corrige:
- A célula recém-construída
- Os vizinhos diretos
- Os vizinhos dos vizinhos
E assim sucessivamente.
Esse processo garante que toda a malha viária permaneça consistente.
Integrando o Road Builder ao Sistema Principal
Para utilizar o Road Builder foi necessário integrá-lo ao script principal chamado Builder.
Primeiro criamos uma referência:
var road_builderDepois instanciamos o objeto:
road_builder = RoadBuilder.new()
add_child(road_builder)Em seguida, passamos a referência do próprio Builder:
road_builder.builder = selfIsso permite que o Road Builder tenha acesso às informações necessárias para modificar o GridMap e manipular as estruturas.
Corrigindo Estradas ao Construir
Sempre que uma nova estrutura é construída, chamamos:
road_builder.road_fix(position)Essa função atua como ponto de entrada do sistema.
Ela é responsável por:
- Corrigir a célula atual
- Corrigir os vizinhos front
- Corrigir os vizinhos back
- Corrigir os vizinhos left
- Corrigir os vizinhos right
- Atualizar toda a rede afetada
Corrigindo Estradas ao Demolir
O mesmo princípio vale quando uma estrada é removida.
Ao demolir uma estrutura, as conexões ao redor mudam.
Por isso, na função de demolição, chamamos:
road_builder.fix_neighbors(position)Nesse caso não precisamos corrigir a célula destruída, apenas os vizinhos que permaneceram no mapa.
Preparando o Caminho para Sistemas Mais Avançados
Embora o objetivo inicial seja facilitar a construção de estradas, esse sistema abre portas para recursos muito mais sofisticados.
Entre eles:
- Sistema de tráfego
- Transporte de recursos
- Caminhos de NPCs
- Expansão urbana
- Rotas comerciais
- Transporte público
Como toda a malha viária já está organizada e conectada automaticamente, futuras mecânicas podem utilizar essas informações sem a necessidade de retrabalho.
Assista ao Vídeo
Criar um sistema de estradas semiautomático é um passo fundamental para qualquer City Builder. Utilizando uma combinação simples de verificação de vizinhos e flags binárias, é possível construir uma solução eficiente, escalável e fácil de manter.
Além de melhorar a experiência do jogador, o sistema serve como base para praticamente todas as mecânicas de mobilidade e logística que serão implementadas futuramente.
No próximo passo da série, o sistema será expandido com o Road Placer, uma ferramenta capaz de criar automaticamente trechos inteiros de estrada apenas selecionando o ponto inicial e o ponto final da construção.


Deixe um comentário