Implementando um cenário destrutível 2D (como Worms)
76
Quais etapas estariam envolvidas na construção de um cenário 2D destrutível, como no Worms? Idealmente, quais são algumas das maneiras pelas quais esse processo pode se tornar mais eficiente possível?
Excelente pergunta. Worms tem dois desafios: destrutibilidade e também movimentos em ângulos estranhos.
ashes999
Eu acho que isso já foi perguntado aqui várias vezes
Vishnu
2
Vish, os links relacionados não parecem sugerir isso.
The Duck comunista
3
Você pode verificar como isso é feito no Hedgewars - é o clone Worms de código aberto.
GVS
Não é suficiente para uma resposta, mas você também pode conferir o Clonk . É um jogo 2D mais antigo de um desenvolvedor alemão que também tinha um cenário destrutível, até pixels específicos. Não está mais em desenvolvimento, mas o código fonte está disponível no link acima. Há também o sucessor de código aberto OpenClonk, mas a partir dos vídeos, parece que ele se afastou da destruição perfeita de pixels e deu uma guinada na direção de Terraria, com tipos de blocos que podem ser destruídos.
Christian
Respostas:
47
Não sei como a paisagem em worms foi implementada exatamente, mas tenho certeza de que eles usaram um bitmap para a paisagem (pelo menos nos jogos mais antigos da série).
Uma abordagem muito básica seria uma imagem de bitmap (P / B), em que pixels pretos representam ar e pixels brancos representam terra . A destruição da paisagem pode ser feita facilmente usando operações de pixel. Portanto, se um foguete atingir o chão, pinte um círculo preto radius = blastRadiusno ponto de impacto.
Você pode renderizar seu mundo (ou apenas uma parte dele) usando esse bitmap. Para um melhor desempenho, sugiro que você o implemente de maneira a atualizar / renderizar apenas uma parte do "mundo". Por exemplo. se algumas partes da paisagem forem destruídas por um foguete, apenas renderize novamente as áreas afetadas, não o mundo inteiro.
Em vez de uma imagem em preto e branco como seu "mapa de colisão", você também pode usar uma imagem de 24 bits na qual usa dois canais para armazenar a superfície normal (x, y) por pixel e um canal para armazenar a "colisão" real mapa". Ter o normal da superfície em mãos ajudará bastante a calcular granadas saltitantes ou a determinar se um personagem pode se mover em uma determinada direção.
Armazenar informações extras é um mapa de colisão, é uma bela ideia.
Deft_code 6/04/11
6
Uma possibilidade em cima da minha cabeça:
Use uma representação de caminho de gráficos vetoriais para armazenar o contorno da "terra" destrutível. Quando ocorre um evento de destruição (por exemplo, uma granada), a área da explosão, representada como um círculo, seria removida do caminho terrestre por meio de uma operação de subtração booleana. O caminho resultante representa o novo "terreno" para detecção de colisão no solo e também possivelmente uma máscara para desenhar o terreno.
Eu acho que é assim que a Hedgewars faz isso. @ Bill, você pode dar uma olhada, já que é de código aberto.
Gastón
2
@ Gastón Os mapas em Hedgewars são todos imagens (PNGs). Duvido que eles estejam sendo convertidos em gráficos vetoriais. Além disso: o uso de gráficos vetoriais (splines, bezier etc.) é muito mais pesado para a CPU, como detecção de colisão ou subtração de formas. Olhando para a fonte é uma boa idéia embora (embora o estilo de codificação é bastante ruim :))
bummzack
4
Geometria computacional como essa pode ficar MUITO complicada, MUITO rápida!
Adam Harte
A pesquisa no "terreno destrutível do box2d" agora oferece algumas demos vetoriais executáveis.
Ciro Santilli # 14/17
6
Use geometria sólida construtiva
Escrevi uma prova de conceito que usava geometria sólida construtiva para lidar com terrenos destrutíveis. Usei o GLU Tessellator para executar as operações booleanas. A documentação explica como, procure "Utilizações CSG para regras de enrolamento" .
Alimentei a saída triangular do mosaico como polígonos estáticos no Box2D. O PoC funcionou muito bem. Consegui subtrair arbitrariamente e adicionar terreno em tempo real, e o terreno continuou a se comportar adequadamente com o Box2D. O único problema real foi que o mosaico GLU pode produzir triângulos degenerados dos quais o Box2D não gosta, então tive que filtrá-los manualmente.
O próximo passo no PoC (do qual nunca cheguei) foi usar o algoritmo SCC da biblioteca de gráficos de impulso para detectar quando um pedaço do terreno foi cortado (cortar o topo de uma montanha). O terreno cortado ainda seria destrutível, mas agora representado por um corpo Box2D dinâmico (não estático) com os triângulos anexados como formas. Eu tinha o design elaborado, mas perdi o interesse quando comecei a pesquisar na documentação do impulso. Eu "planejo" revisitar a idéia quando eu fizer um jogo de terra / Worms queimado algum dia.
Todas as respostas acima falam sobre a implementação do caso mais simples, como em worms. Ou seja, quando a área de impacto é destruída e todo o resto é intocado. Você considerou que sua paisagem pode eventualmente ser dividida em duas? Digamos, há uma montanha e os jogadores cortam o fundo dela com um lançador de foguetes. Agora, a montanha não deveria cair? Além disso, seria natural que uma paisagem fosse um pouco elástica. Na época do Worms (pelo menos eu me lembro deles, eu não joguei o Worms por, durante muitos anos), os computadores não eram fortes o suficiente para fazer o certo. Mas eles estão agora.
Obviamente, depende totalmente das ambições do seu projeto. Mas se você quer que seja realmente incrível, talvez você deva experimentar o Box2D como um mecanismo de física. Você pode fazer muito com isso.
Nos vermes, você pode cavar um buraco na paisagem usando uma tocha. Não seria tão engraçado se esse túnel simplesmente desabasse em seu pobre verme empunhando uma tocha. Também era possível ter pedaços da paisagem "flutuando" no ar. Sua proposta parece uma ideia divertida, não apenas como um jogo de Worms.
bummzack
Esse era o ponto, eu estava pensando em variações dessa jogabilidade. Além disso, algumas partes da paisagem podem ser indestrutíveis e / ou permanentemente suspensas no ar, o que permitiria criar blocos "flutuantes". Além disso, alguns poderiam ter força constante aplicada a eles, puxando-os para cima ou para os lados, como o que as bolas de ar faziam no World of Goo.
Septagram
É engraçado, porque eu estava pensando em fazer um jogo como esse, seria uma reviravolta divertida para o mecânico Worms. A idéia de corpos rígidos de bitmap seria definitivamente um tópico interessante por si só, embora a complexidade esteja um pouco acima da minha cabeça.
William Casarin
Bem, nesse caso, corpos rígidos de bitmap seriam um impedimento; em vez disso, eu faria uma paisagem como uma grade triagonal de vértices, conectados elasticamente. Você já jogou world of goo? Caso contrário, veja as capturas de tela: vgchartz.com/games/pics/6644424aaa.jpg doublegames.de/images/screenshots/world-of-goo_1_big.jpg . Não, não, não, não, se você não tocou, é absolutamente necessário :) Agora imagine que, em vez de bolas de gosma, cada triângulo exiba parte da textura da sua paisagem e elas são muito menores. Mexer com constantes e sua paisagem vai ser muito difícil, ou macio como uma geléia
Septagram
2
dê uma olhada no mecanismo físico . Todo o mecanismo é baseado na idéia de que tudo é uma estrutura deformada / destrutível (como uma torre de gosma).
Deft_code
3
Como bummzack disse Bitmaps. Embora você possa usar transparências de 1 bit ou se você não tiver esse suporte, use uma cor rosa horrível que você não usará em seu jogo.
O ponto de impacto pode ser calculado apenas verificando a cor do pixel. e quando ocorrer um impacto, altere a cor (ou exclua-a) do bitmap.
Quanto ao raio de explosão, minha primeira parada seria o algoritmo de círculo de Bresenham , muito rápido e eficiente. Embora eu faça um apagamento rápido primeiro com algo como um quadrado e coloque o círculo em volta para obter as bordas.
Respostas:
Não sei como a paisagem em worms foi implementada exatamente, mas tenho certeza de que eles usaram um bitmap para a paisagem (pelo menos nos jogos mais antigos da série).
Uma abordagem muito básica seria uma imagem de bitmap (P / B), em que pixels pretos representam ar e pixels brancos representam terra . A destruição da paisagem pode ser feita facilmente usando operações de pixel. Portanto, se um foguete atingir o chão, pinte um círculo preto
radius = blastRadius
no ponto de impacto.Você pode renderizar seu mundo (ou apenas uma parte dele) usando esse bitmap. Para um melhor desempenho, sugiro que você o implemente de maneira a atualizar / renderizar apenas uma parte do "mundo". Por exemplo. se algumas partes da paisagem forem destruídas por um foguete, apenas renderize novamente as áreas afetadas, não o mundo inteiro.
Em vez de uma imagem em preto e branco como seu "mapa de colisão", você também pode usar uma imagem de 24 bits na qual usa dois canais para armazenar a superfície normal (x, y) por pixel e um canal para armazenar a "colisão" real mapa". Ter o normal da superfície em mãos ajudará bastante a calcular granadas saltitantes ou a determinar se um personagem pode se mover em uma determinada direção.
fonte
Uma possibilidade em cima da minha cabeça:
Use uma representação de caminho de gráficos vetoriais para armazenar o contorno da "terra" destrutível. Quando ocorre um evento de destruição (por exemplo, uma granada), a área da explosão, representada como um círculo, seria removida do caminho terrestre por meio de uma operação de subtração booleana. O caminho resultante representa o novo "terreno" para detecção de colisão no solo e também possivelmente uma máscara para desenhar o terreno.
fonte
Use geometria sólida construtiva
Escrevi uma prova de conceito que usava geometria sólida construtiva para lidar com terrenos destrutíveis. Usei o GLU Tessellator para executar as operações booleanas. A documentação explica como, procure "Utilizações CSG para regras de enrolamento" .
Alimentei a saída triangular do mosaico como polígonos estáticos no Box2D. O PoC funcionou muito bem. Consegui subtrair arbitrariamente e adicionar terreno em tempo real, e o terreno continuou a se comportar adequadamente com o Box2D. O único problema real foi que o mosaico GLU pode produzir triângulos degenerados dos quais o Box2D não gosta, então tive que filtrá-los manualmente.
O próximo passo no PoC (do qual nunca cheguei) foi usar o algoritmo SCC da biblioteca de gráficos de impulso para detectar quando um pedaço do terreno foi cortado (cortar o topo de uma montanha). O terreno cortado ainda seria destrutível, mas agora representado por um corpo Box2D dinâmico (não estático) com os triângulos anexados como formas. Eu tinha o design elaborado, mas perdi o interesse quando comecei a pesquisar na documentação do impulso. Eu "planejo" revisitar a idéia quando eu fizer um jogo de terra / Worms queimado algum dia.
fonte
Todas as respostas acima falam sobre a implementação do caso mais simples, como em worms. Ou seja, quando a área de impacto é destruída e todo o resto é intocado. Você considerou que sua paisagem pode eventualmente ser dividida em duas? Digamos, há uma montanha e os jogadores cortam o fundo dela com um lançador de foguetes. Agora, a montanha não deveria cair? Além disso, seria natural que uma paisagem fosse um pouco elástica. Na época do Worms (pelo menos eu me lembro deles, eu não joguei o Worms por, durante muitos anos), os computadores não eram fortes o suficiente para fazer o certo. Mas eles estão agora.
Obviamente, depende totalmente das ambições do seu projeto. Mas se você quer que seja realmente incrível, talvez você deva experimentar o Box2D como um mecanismo de física. Você pode fazer muito com isso.
fonte
Como bummzack disse Bitmaps. Embora você possa usar transparências de 1 bit ou se você não tiver esse suporte, use uma cor rosa horrível que você não usará em seu jogo.
O ponto de impacto pode ser calculado apenas verificando a cor do pixel. e quando ocorrer um impacto, altere a cor (ou exclua-a) do bitmap.
Quanto ao raio de explosão, minha primeira parada seria o algoritmo de círculo de Bresenham , muito rápido e eficiente. Embora eu faça um apagamento rápido primeiro com algo como um quadrado e coloque o círculo em volta para obter as bordas.
fonte