Estou verificando a colisão quanto a um personagem de jogo de plataforma, como mostra o item 1. Os pontos vermelhos são os pixels marcados e as linhas cinza indicam os eixos aos quais pertencem. Gosto dos resultados obtidos ao verificar a colisão dessa maneira (versus, digamos, caixa delimitadora). Tudo funciona exatamente como eu gostaria, exceto por um problema: detecção de esmagamento.
Nas imagens a seguir, a caixa azul clara representa o chão, a caixa laranja é um objeto e as setas indicam a direção do movimento.
A solução simples para detectar quando o jogador é esmagado é verificar se os pontos de colisão em lados opostos estão sendo acionados. Se estiverem, o jogador está sendo esmagado. No segundo, você pode ver um cenário de queda normal. O jogador está aterrado e os pontos de colisão superiores estão se cruzando com o objeto em queda. Isso desencadeia uma queda.
Os números 3, 4 e 5 apresentam cenários problemáticos. Em # 3, o jogador está se movendo em direção ao objeto, que está se movendo para cima. Um ponto de colisão do lado direito está atingindo o objeto, causando uma colisão e parando o jogador.
Agora, se o objeto continuar se movendo para cima e o jogador continuar se movendo para a direita (como mostra a # 4), o objeto limpa o ponto de colisão do lado direito do jogador e o jogador se move para a direita. Mas agora, tendo feito isso, o objeto está cruzando um ponto de colisão superior, causando uma queda vertical indesejada.
Um cenário semelhante é mostrado em # 5. Dois objetos estão suficientemente distantes para que os pontos de colisão inferiores desapareçam, permitindo que o jogador caia, mas não o suficiente para permitir que os pontos de colisão laterais desapareçam, causando uma queda horizontal indesejada.
Estive procurando meu cérebro em uma solução, mas nada que tenha surgido funcionou particularmente bem, por isso estou me perguntando se alguém por aí tem uma ideia ou insight sobre como resolver esses problemas.
Para esclarecer alguma confusão, os pontos de colisão vermelhos estariam dentro do sprite e as linhas cinza foram usadas apenas para indicar o eixo relevante para cada ponto de colisão. Por exemplo, se o sprite do personagem fosse um quadrado verde simples, os pontos de colisão teriam algo parecido com isto:
fonte
Faça com que os pontos de "teste de esmagamento" estejam dentro da caixa cinza mostrada na sua imagem # 1 - ou seja, mate o jogador apenas se detectar um acerto em um dos pixels lá.
fonte
Como alguém que cresceu com plataformas dos anos 80, meu primeiro comentário é que os pontos de contato devem estar exatamente no sprite, e não em qualquer lugar fora dele. Houve poucas experiências mais frustrantes do que morrer quando uma arma / triturador / inimigo estava claramente a vários pixels de seu personagem - e esse tipo de experiência é o que impede as pessoas de jogar.
Com isso em mente, a idéia de ter pontos separados para colisão horizontal e vertical simplesmente não voa. Portanto, seus casos 3 e 5 não existem.
Quanto à detecção de colisão, como foi dito anteriormente, é necessário considerar a direção do movimento e você tem dois eixos de movimento a considerar. Se um britador estiver abaixado, o jogador não poderá andar para frente - ele deve agir como uma parede. Portanto, com pontos de detecção horizontais e verticais no mesmo local, você não pode obter o caso 4, mesmo antes de adicionar a direção do movimento à mistura.
O triturador ascendente adiciona complexidade extra. Se é tão rápido que o jogador não tem chance de escapar, tudo bem. Mas, se for mais lento, o jogador espera poder correr sobre a plataforma ascendente e pular do outro lado. O sprite do jogador sobe no triturador e a detecção de esmagamento acontece no teto .
fonte
Você pode tornar o objeto "mais duro" que o chão, o que significa que, assumindo uma colisão, o jogador é empurrado "para dentro" do chão, em vez de ser empurrado "para dentro" do objeto em movimento.
Isso pressupõe que o jogador não consiga empurrar-se "contra" objetos ou chão.
fonte
Se você puder detectar a sobreposição de objetos sem precisar esperar a exibição, uma abordagem simples é processar o movimento para o player e outros objetos de forma independente, um pixel de cada vez, com verificações de colisão separadas posteriormente. Se o jogador estiver se movendo livremente e colidir com seu objeto como resultado de tal movimento, afaste-o. Se ocorrer uma colisão com um objeto como resultado do movimento do objeto, verifique se o jogador pode se mover na mesma direção que esse objeto. Nesse caso, mova o player. Caso contrário, lide com a situação de "esmagamento" adequadamente (danificando ou matando o jogador e / ou movendo o objeto em colisão para trás, dependendo do contato).
BTW, se apenas um número limitado de combinações de formas puder colidir, pode ser útil pré-calcular bitmaps de "detecção de colisão", de modo que, se um pixel for definido no primeiro sprite no deslocamento (x1, y1) e no segundo no deslocamento (x2, y2) do segundo, o pixel no deslocamento (x1-x2, y1-y2) será definido no mapa de colisão. Esse mapa de colisão pré-calculado permitirá detectar colisões entre os dois sprites, verificando o estado de um único pixel no mapa de colisão.
fonte
São necessários dois objetos para esmagar um jogador. Sua detecção de queda deve verificar se o jogador está entre dois objetos, o espaço entre eles é igual ao tamanho do jogador e a distância diminuindo.
fonte
Acho que estou trabalhando até agora. Ele não requer informações "externas" sobre o movimento dos trituradores e resolve o problema dos falsos positivos. Quando um falso positivo é detectado, ele é tratado como colisão (e é isso que realmente é):
A idéia é: por que verificar se o britador está se movendo quando realmente nos importamos se o personagem está se movendo? Ambos podem responder se a queda é falsa positiva causada pelo movimento do próprio personagem ou queda verdadeira pelo movimento do objeto triturador.
Se o personagem estiver se movendo e esmagado (colisões nos lados opostos para o quadro recebido), verifique novamente se há esmagamento nas últimas coordenadas do quadro / iteração:
Se não for confirmado novamente, é devido ao próprio movimento do personagem e o personagem deve ser retornado para as últimas coordenadas de quadro / iteração como uma colisão
Se a queda for confirmada pela segunda vez, prossiga com a queda.
fonte