Implementação do algorítmo Wave Function Collapse (WFC)

Mini projeto em P5.js que implementa uma versão básica do algoritmo Wave Function Collapse (WFC) para gerar padrões baseados em ladrilhos (tiles). O WFC é um algoritmo de geração procedural que cria padrões complexos a partir de regras locais. Ele começa com um estado "não observado" (todas as possibilidades estão abertas para cada ladrilho) e as "colapsa" com base em regras e observações.
⚙️ Como Funciona
A ideia central por trás desta implementação do WFC é:
Ladrilhos (Tiles): Cada ladrilho possui "bordas" definidas (representadas como strings como "AAA" ou "ABA"). Essas bordas ditam como os ladrilhos podem se conectar uns aos outros.
Propagação: Quando um ladrilho é "colapsado" (ou seja, seu tipo é escolhido para uma célula específica da grade), as opções de ladrilhos possíveis para seus vizinhos são reduzidas com base nas bordas do ladrilho colapsado. Isso "propaga" as restrições por toda a grade.
Entropia: O algoritmo prioriza o colapso de células com a menor "entropia" (ou seja, o menor número de opções de ladrilhos restantes). Isso ajuda a resolver primeiro as áreas de alta restrição.
🛠️ Tecnologias Utilizadas
JavaScript: A linguagem de programação principal.
p5.js: Uma biblioteca JavaScript para programação criativa, usada para renderizar gráficos e lidar com funções básicas de desenho.
✨ Funcionalidades Principais
Definição de Ladrilhos: Os ladrilhos são definidos com imagens e padrões de bordas, permitindo várias regras de conexão.
Regras de Adjacência Automáticas: O sistema analisa automaticamente as bordas de cada ladrilho para determinar quais outros ladrilhos podem ser colocados ao seu lado.
Colapso Baseado em Entropia: O algoritmo escolhe inteligentemente a próxima célula a ser colapsada, encontrando aquela com o menor número de opções de ladrilhos possíveis, guiando o processo de geração.
Depuração Visual:
Células Colapsadas: Exibem a imagem do ladrilho escolhido.
Células Não Colapsadas: Mostram o número de opções de ladrilhos restantes para aquela célula, fornecendo feedback visual sobre a entropia.
Guia de Ladrilhos: Um guia visual no lado direito da tela exibe todos os ladrilhos disponíveis e seus respectivos índices, útil para entender o conjunto de ladrilhos.
Propagação Passo a Passo: A função
propagate
usasetTimeout
para introduzir um atraso, permitindo que você observe visualmente o processo passo a passo de colapso e propagação do algoritmo WFC.
🎮 Demonstração
🧩 Classes
Tile
Representa um único tipo de ladrilho.
img
: O objeto de imagem p5.js para o ladrilho.edges
: Um array de strings representando as bordas do ladrilho (ex:["top", "right", "bottom", "left"]
).analyze(tiles)
: Um método (provavelmente dentro da classeTile
) que pré-calcula vizinhos válidos para cada lado do ladrilho, comparando suas bordas com todos os outros ladrilhos disponíveis.rotate(numRotations)
: Um método para criar um novo objetoTile
que é uma versão rotacionada do original, atualizando sua imagem e padrões de bordas de acordo.
Cell
Representa uma única célula na grade.
options
: Um array de índices representando os tipos deTile
possíveis que podem ser colocados nesta célula.collapsed
: Um booleano indicando se um ladrilho foi escolhido para esta célula.
🚀 Funções Chave
preload()
: Carrega as imagens dos ladrilhos antes do início do esboço.setup()
: Inicializa a tela, define os ladrilhos base, os rotaciona para criar variações, analisa as regras de adjacência para todos os ladrilhos e inicializa agrid
com todas as opções de ladrilhos possíveis para cada célula.draw()
: O loop principal onde o algoritmo WFC é iniciado. Ele escolhe uma célula inicial aleatória e um ladrilho aleatório para colapsar e então chamapropagate
para iniciar o efeito cascata. É definido comonoLoop()
para rodar apenas uma vez após o colapso inicial.drawGrid()
: Renderiza o estado atual da grade, mostrando os ladrilhos colapsados ou o número de opções para as células não colapsadas. Também exibe o guia de ladrilhos.drawText(pos, string, color)
: Função auxiliar para desenhar texto na tela, usada principalmente para exibir o número de opções em uma célula.drawCell(pos, color)
: Função auxiliar para desenhar um retângulo colorido para células não colapsadas.isValidNeighbor(neighbor)
: Verifica se as coordenadas de um vizinho estão dentro dos limites da grade e se a célula vizinha ainda não foi colapsada.getNeighbors(pos)
: Retorna as coordenadas dos quatro vizinhos diretos de uma dada célula, juntamente com o lado da célula atual que está voltado para o vizinho.getValidNeighbors(pos)
: Filtra os resultados degetNeighbors
para retornar apenas vizinhos válidos e não colapsados.intersectArrays(arr1, arr2)
: Uma função utilitária para encontrar elementos comuns entre dois arrays. Isso é crucial para reduzir opções durante a propagação.addGlobalNeighbor(neighbor, cell)
: Adiciona uma célula vizinha válida e não colapsada a uma lista global (neighborsCells
) para ser processada posteriormente durante a propagação. Esta lista garante que cada vizinho não colapsado seja considerado apenas uma vez.propagate(pos, tile)
: O coração do algoritmo WFC:Marca a célula atual em
pos
como colapsada e atribui a ela otile
.Identifica vizinhos válidos e não colapsados.
Para cada vizinho, atualiza suas
options
intersectando-as com os ladrilhos permitidos com base nas bordas dotile
atual.Adiciona a célula vizinha atualizada a
neighborsCells
se ainda não estiver lá.Chama-se recursivamente com a próxima célula a colapsar, escolhida de
neighborsCells
como aquela com o menor número de opções (menor entropia). UmsetTimeout
é usado para visualizar o processo.
📋 Constantes e Variáveis
TILE_SIZE
: O tamanho em pixels de cada ladrilho.W
,H
: A largura e altura da grade em ladrilhos.tiles
: Um array que armazena todos os objetosTile
(incluindo as versões rotacionadas).grid
: Um array 2D de objetosCell
representando a grade WFC.gridImgs
: Um array 2D para armazenar o objetoTile
uma vez que uma célula é colapsada.neighborsCells
: Um array global usado durante a propagação para rastrear as células vizinhas não colapsadas que precisam ter suas opções atualizadas, classificadas por entropia.IT
: Um contador de iterações para prevenir loops infinitos durante a propagação (definido como 100).imgT
,imgI
,imgL
,imgB
: Objetosp5.Image
carregados empreload
para diferentes tipos de ladrilhos.
Subscribe to my newsletter
Read articles from Joismar Braga directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
