Colisão 2D rápida e precisa

17

Estou trabalhando em um jogo de tiro 2D de cima para baixo e agora preciso ir além do meu sistema básico de colisão de caixas delimitadoras de retângulos.

Eu tenho grandes níveis com muitos sprites diferentes, todos com formas e tamanhos diferentes. As texturas dos sprites são todos arquivos png quadrados com fundos transparentes, então eu também preciso de uma maneira de ter uma colisão apenas quando o jogador entrar na parte colorida da textura, e não no fundo transparente.

Planejo lidar com a colisão da seguinte maneira:

  1. Verifique se existem sprites ao alcance do jogador
  2. Faça um teste de colisão de caixa delimitadora
  3. Faça uma colisão precisa (onde eu preciso de ajuda)

Não me importo com técnicas avançadas, pois quero acertar isso com todos os meus requisitos em mente, mas não sei como abordar isso. Quais técnicas ou mesmo bibliotecas para tentar. Sei que provavelmente precisarei criar e armazenar algum tipo de forma que represente com precisão cada sprite menos o plano de fundo transparente.

Eu li que por pixel é lento, então, considerando meus grandes níveis e número de objetos, acho que não seria adequado. Também examinei o Box2d, mas não consegui encontrar muita documentação ou exemplos de como colocá-lo em funcionamento com SFML.

Neófito
fonte

Respostas:

18
  1. Etapa 1, crie uma grade e atualize-a para cada objeto que se mover.
  2. Verifique apenas se há colisões entre objetos nos mesmos quadrados.
  3. Verifique se a caixa delimitadora dos objetos se cruza (seu retângulo contendo).
  4. Verifique a colisão perfeita de pixels usando uma versão de baixa resolução do contorno (consulte Física do jogo).
  5. Faça uma verificação normal do traçado de estrutura de tópicos, conforme descrito em Game Physics (Q 2)

Passo 1:

Crie uma matriz 2D da grade. Todo objeto sabe em que quadrado ocupa sua posição x, y, sua largura e altura. Se um objeto é afastado, ele sai do quadrado antigo e atualiza o novo quadrado que está ocupando.

Isso leva apenas O (n) no total para n objetos. Para qualquer objeto específico O (1).

Passo 2:

Execute todas as verificações de colisões entre objetos nos mesmos quadrados. Não há necessidade de executar testes para colisões entre objetos em diferentes quadrados. Um objeto pode ocupar até quatro quadrados se tiver tamanho médio. Isso significa muito poucas verificações.

Etapa 3:

Verifique a interseção entre os retângulos dos objetos. Se não houver interseção, pare.

Passo 4:

Verifique se há colisões perfeitas em pixels entre os contornos dos objetos apenas dentro da área de interseção. Deve ser rápido o suficiente. Caso contrário, crie uma matriz 2d-booleana de baixa resolução e verifique-a primeiro; se você encontrar colisões, precisará verificar apenas um pequeno segmento na matriz 2d de alta resolução, economizando um tempo precioso.

Por favor, leia isto para o conceito de como dividir seu mundo de jogo em uma grade de quadrados:

Criando um sistema eficiente de detecção de colisões

Leia isto para intuição sobre como detectar colisões perfeitas em pixels .

Física dos jogos / Detecção de colisão 2D AS3

Você pode melhorar significativamente o desempenho:

  1. Salvando uma versão de baixa resolução (1/16) do esquema para comparar primeiro.

  2. Somente verificando na área onde as duas rects se cruzam.

  3. dividindo o contorno aproximadamente em segmentos e verificando apenas colisões entre os segmentos primeiro.

Por favor, sinta-se à vontade para comentar e vou elaborar.

verifique na área de interseção

wolfdawn
fonte
1
Como Arthur disse, substitua as etapas 1. e 2. por uma grade e, para detecção precisa de colisões, você pode usar uma versão de baixa resolução de suas imagens.
Markus von Broady
1
E se você realmente precisa, você também pode usar uma técnica semelhante à minha resposta aqui: gamedev.stackexchange.com/questions/38481/...
Markus von Broady
Markus aponta uma boa ideia. Você deve usar uma matriz 2d-booleana ou uma matriz 1d que seja tratada como 2d e poderá salvar 1/2 1/4 1/8 de versões em baixa resolução dessa matriz para acelerar as coisas. Provavelmente, isso não será necessário, pois a computação em matrizes 2d-booleanas é muito rápida. Ainda é uma ferramenta útil para ter.
wolfdawn
Se o jogador estiver totalmente contido dentro de um quadrado na grade, você poderá verificar apenas os objetos naquele quadrado. O jogador pode estar em quatro quadrados adjacentes ao mesmo tempo. É isso que você quer dizer? Se você quer dizer a interseção entre retângulos, sim, você só precisará verificar colisões se elas se cruzarem.
Lobo
1
Espero que a atualização ajude a esclarecer as coisas. Depois de escrever algum código, você pode publicá-lo na revisão do código e nos vincular para comentários. Veja como é
fácil fazer o