Pergunta

Espero que isso fique claro o suficiente.

Eu tenho um mapa 2D feito de ladrilhos e quero que a "água" viaje por este mapa. Ele sai de um cano em um ladrilho específico e, em seguida, precisa encher, como água, todos os ladrilhos para alcançar um outro ladrilho. Atualmente, tenho o mapa inserido no jogo, com cada ladrilho sendo um nó e cada nó com conexões com todos os ladrilhos apropriados ao seu redor. Eu tenho os nós armazenados em uma matriz classificada, primeiro por x, depois por y. Além disso, alguns ladrilhos são peças de 'portão', que podem impedir que a água flua através delas. Estes fazem parte da mesma grade de ladrilhos de nós e são apenas sinalizados quando ativos.

O problema é como disperso a água.

Inicialmente, eu tinha cada tubo (que caiu água) acompanha uma lista de ladrilhos de água 'atual' e 'completa', e dispersava água diretamente para os azulejos 'atuais' e depois os trocava para sua lista 'completa' quando apropriado. A lista 'atual' foi expandida, obtendo os ladrilhos circundantes dos ladrilhos já 'atuais'. De qualquer forma, isso funcionou bem, e a água fluía bem, mas eu não conseguia descobrir como fazê-la funcionar com os portões para que o fluxo de água pudesse ser interrompido e republicado (e parado novamente, etc. ) em um ponto específico.

No momento, eu o tenho onde a água despeja em um e apenas um ladrilho, e então, enquanto um ladrilho tem muita água, ele empurra a água incrementalmente para um azulejo vizinho aleatório (a menos que o ladrilho seja um portão ativo.) O problema com isso é que a água 'sloshes' em torno de ladrilhos já cheios em vez de fluir 'para fora'. Ele chegará lá eventualmente, mas o fluxo é muito menos natural.

Assim conclui meu dilema.

O código está escrito em Python.

EDIT: Nova ideia. Eu poderia fazer a pesquisa de tubos através dos nós para um ladrilho livre adequado para colocar a água a cada atualização, mas isso parece terrivelmente ineficiente-particularmente com vários tubos.

Foi útil?

Solução

Isso surge muito no desenvolvimento de jogos - houve muitas negociações no GDC e artigos de destaque de gamasutra/desenvolvedor de jogos sobre esse assunto. O melhor para seus propósitos, eu acho que é Jos StamS "Dinâmica de fluidos em tempo real para jogos"Do GDC de 2003.

Ele descreve uma maneira simplificada de executar advecção através de um backtrace linear que sofre de alguns problemas, mas funciona muito bem para fluidos incompressíveis (ou seja, funciona melhor para a água do que para o gás). Backtrace linear significa basicamente que ele configura uma grade representando a densidade do fluido em cada ponto do espaço (que são seus ladrilhos) e, em seguida, para cada quadro visita cada ponto e pergunta: "Com base na pressão nos pontos circundantes, onde está o fluido provavelmente para vem de onde? "Isso acaba sendo mais fácil do que resolvê -lo de outra maneira (" Para onde o fluido está indo? ").

Artigo de Mick West sobre Dinâmica de Fluidos Para Gamasutra, estende o artigo de Stam de certa forma que possa melhorar o desempenho, portanto, você pode começar por aí.

Há também Um artigo Gamedev recente patrocinado pela Intel que oferece uma solução mais completa, mas é bastante complicado e focado mais no lado gráfico de renderização em 3D.

Você pode olhar para Fortaleza anã Para um exemplo de mecânica de líquido 2D de azulejos, mas sua solução parece ter um monte de problemas para lidar com fluidos de fluxo rápido ou pressurizado; Às vezes, sua água se move muito mais lentamente do que você esperaria, ou é pego em quarteirões e cantos.

Esses papéis resumem muito melhor a matemática e o algoritmo melhor do que eu poderia enfiar em uma caixa de transbordamento de pilha, mas há dois pontos gerais que eu gostaria de fazer também:

  1. A simulação de água é muito computacional. Como você está trabalhando no Python, isso pode resultar em um problema de desempenho real - certifique -se de configurar alguns meios de perfil do seu algoritmo para encontrar os pontos de acesso, caso seu loop demore tanto que mate a quadros. Você pode ter que recorrer a Python numérico Para obter operações rápidas de matriz baseada em C.
  2. Há muito mais matemática no desenvolvimento de jogos do que a maioria das pessoas espera!

Outras dicas

Algumas heurísticas sobre as suposições:

  • "gotas" discretas que ocupam exatamente um quadrado cada
  • A água nunca permanece mais de um alto em um determinado ladrilho,
  • A água sempre permanece contínua
  • Quando as barreiras estão em alta, elas são como paredes
  • Quando as barreiras estão abaixadas, elas são como quadrados abertos

Para cada poça, mantenha uma lista de quadrados de borda e quadrados abertos ao lado das bordas.

Quando uma barreira desce

amend the lists of edge and open squares for any puddles that were touching it

Quando uma barreira sobe

if (it was covered)
    pick a non-wall square next to it at random, and add the drop from the barrier there.
amend the lists of edge and open squares for any puddles next to the block

Quando você adiciona uma gota:

if (the square "under" the pipe is empty)
   fill it
else
   consult the list of edge square associated with the pool under the pipe, and select the one closest to the pipe (if more than one is closest, choose from the candidates at random), and fill it.  
amend the lists of edge and open squares for the puddle (be prepared to merge with neighboring puddles if necessary)

Quando você remove uma gota

 find the edge (not open!) square farthest from the sink (or randomly select from the equivalent candidates), and empty it
 amend the lists of edge and open squares for the puddle

(Um babado disponível aqui é tornar o "mais distante" delimitado por distância igual a outras pias, de modo que os quadrados no meio de uma poça podem ficar vazios se estiverem entre as pias)

Isso não é muito realista e não recebe dinâmica para você falar, mas manterá poças contínuas "em" os tubos de pingos e preencherá o espaço disponível, com gotejamentos suficientes.

Seu modelo inclui um conceito de diferença de potencial ou pressão?

Digamos que um ladrilho vazio tenha pressão zero, um ladrilho completo uma pressão de 10. Se houver um tubo entre dois ladrilhos, a água flui para equalizar a pressão, um portão fecha um tubo para que nada flua.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top