Onde a lógica de detecção de colisão deve ser colocada?

19

Estou desenvolvendo um pequeno mecanismo de jogo 2D. Os caracteres têm um método de pintura que atualmente faz o seguinte:

  1. Calcule a nova posição do personagem de acordo com sua velocidade, etc.
  2. Atualize a célula da grade de colisão **
  3. Desenhe o personagem na nova posição

** Criei uma grade de colisão para reduzir o número de verificações de interseção

Agora, o algoritmo básico que pensei para detectar colisões é:

For Each Character
    Check intersection with characters in surrounding 8 cells

Eu posso simplesmente colocar esse código no método paint. Mas aqui está o problema que antecipo.

Suponha que dois caracteres A e B estejam em células adjacentes na grade de colisão. Agora, conforme o algoritmo acima, na iteração do caractere A, ele detectará que colidiu com B. Na iteração para o caractere B, detectará que colidiu com A.

Mas tenho uma ideia de que, quando A detectar que colidiu com B, deve informar B que colidiu com A. Isso economizaria muitas comparações quando houver mais de dois atores colidindo. Mas não tenho certeza de como lidar com isso. Acho que, em vez de cada personagem checar sua colisão, devo checar a colisão dentro do loop do jogo.

Essa abordagem seria correta? Como você lidou com esse tipo de problema? Eu mesmo pensei na grade da colisão. Existem alternativas à lógica da grade de colisão?

Biscoito
fonte
Lamento nitpick, mas em uma biblioteca especializada em física 2D. Física do jogo é geralmente muito aproximativo, de modo que qualquer solução que não faz jogo não-jogável é bom, mas se você quer resolvê-lo corretamente é só usar a física especializados como Box2D ... :-D
user712092

Respostas:

14

A abordagem usual para a detecção de colisões é não ter A ou B detectar colisões por conta própria.

Em vez disso, você primeiro move todos os objetos e, em seguida, faz com que um sistema de colisão separado procure colisões entre todos os pares de objetos, informando cada objeto sobre as coisas com as quais ele colidiu e, finalmente, processando todos os objetos.

Portanto, em essência, em vez de "mover", verifique se há colisões, desenhe "dentro da sua função Paint (), você divide" move "e" draw "em funções separadas que você chama separadamente (primeiro" move "para cada objeto e, em seguida, "desenhar" para cada objeto). E entre eles, verifique se há colisões.

Nota avançada: Se algum de seus objetos se mover em reação a colisões detectadas, talvez seja necessário repetir a etapa "procurar colisões entre todos os pares de objetos", caso a resposta de colisão de um objeto cause outra colisão.

Trevor Powell
fonte
Esta é a maneira correta de fazer as coisas. Deixe que os objetos manejem suas responsabilidades e o sistema de colisão deve decidir o que acontece quando encontrar um obstáculo. Você também pode ter um retângulo / cilindro de colisão (2d / 3d) ao redor dos seus personagens como uma espécie de gatilho inicial.
James P.
Ótimo! Em relação à nota avançada, as colisões não devem ser verificadas novamente apenas para objetos que se movem em reação à colisão e aos objetos com os quais colidem na nova posição? Haverá uma cadeia de verificações, mas evitará verificar a colisão de todos os objetos.
Cracker
Como lidar com isso - gamedev.stackexchange.com/questions/13076/…
Cracker
1

Eu corro um loop para todos os meus personagens no loop do jogo, como você diz.

O jeito que eu faço é com um estado em cada um dos meus personagens, então se A e B colidem enquanto A está verificando a colisão A e B estão definidas para acertar. no início do loop de B, ele verifica se já foi atingido, se esse ID não executa o loop.

Eu coloquei o código de afetação no loop para que qualquer ação que deva ser executada em B tenha acontecido no loop de A, de modo que não haja motivo para B verificar, pois isso atrapalharia o resultado da colisão, mas isso pode ser diferente para você. .

Skeith
fonte
Mas neste caso, quando A detectar interseção com B, B.hit será definido como verdadeiro e, portanto, B não verificará QUALQUER interseção. Mas se outro caractere C cruzar com B, B não o detectará?
Cracker
Desculpe, entendi. Como A não se cruza com C, C.hit ainda será falso. B não verificará colisões. Mas C verificará e passará a informação para B se houver uma colisão entre B e C. Legal!
Cracker
Mas acho que se todos os A, B e C se cruzarem, haverá um problema. A definirá B.hit e C.hit como true. B e C saberão que colidiram com A. Mas, como a propriedade de ocorrência é verdadeira, não verificarão a colisão. A colisão entre B e C passa despercebida.
Cracker
Você pode se infiltrar em um método semelhante, colocando todos os objetos de colisão viáveis ​​em uma coleção de algum tipo e, em seguida, apenas checando a colisão com itens que vêm depois do objeto na coleção. IE: A verifica vs B, C, D; Verificações B vs C, D; C dá check contra D. Cada um atrás não precisa ser checado, pois já havia sido verificado no turno um atrás. Não é tão rápido quanto pular a colisão do elemento completamente, mas é útil mesmo assim.
Lunin