Breakout Collision: Detectando o lado da colisão

10

Estou escrevendo um clone de fuga (meu primeiro jogo) e estou totalmente empolgado com a maneira de descobrir qual lado do tijolo foi atingido.

Eu tenho um método de detecção de colisão que se parece com isso:

DetectCollision(Object a, Object b)

   x = distance(a.x, b.x);
   y = distance(a.y, b.y);

   if (x is smaller than the combined width &  y is smaller is than combined height {
       return true;
   }
return false;  

Isso funciona totalmente bem, mas preciso saber o lado da colisão e a localização em relação ao centro para responder adequadamente.

Passei os últimos dias bisbilhotando, mas estou perdido.

user590903
fonte

Respostas:

13

Tudo isso pode ser obtido da posição da bola em relação à posição do tijolo com o qual colidiu.

Depois de detectar uma colisão:

if(ballPosition.y <= brickPosition.y - (brickHeight/2))
  //Hit was from below the brick

if(ballPosition.y >= brickPosition.y + (brickHeight/2))
  //Hit was from above the brick

if(ballPostion.x < brickPosition.x)
  //Hit was on left

if(ballPostion.x > brickPosition.x)
  //Hit was on right

Os dois primeiros verificam se a bola está acima ou abaixo do tijolo. Se nenhum deles estiver próximo ao tijolo, verifique de que lado está. Isso precisará ser ajustado duas vezes para se ajustar de onde você está tirando o local, por exemplo, brickPosition é o centro do brick ou brickPosition é o canto superior esquerdo.

MichaelHouse
fonte
1
Mas como você usaria isso para reposicionar o player, já que ele se move dentro de um tijolo, várias dessas condições serão atendidas e se você redefinir o x desejado na borda da parede, por exemplo, se ele pressionar a tecla de um tijolo defina o x desejado exatamente ao lado da parede, então não funcionaria realmente porque quando você verifica a posição teórica do personagem para ver de qual direção ele está colidindo, várias dessas condições serão atendidas, então como você use isso para redefinir o player, você precisa adicionar mais no final de cada if)?
22418 Bluejayke
Tanto quanto eu sei, o "jogador" em um jogo tipo breakout é o remo. A raquete não está se movendo dentro de um tijolo, nem você está mudando a posição da raquete com base na interação da bola com os tijolos. Se é isso que você está fazendo, não precisa de lógica adicional, apenas não processe a reposição até ter feito todas as verificações de colisão. Ou retorne assim que uma das verificações for verdadeira.
MichaelHouse
8

Você pode usar o Vector Math para descobrir os ângulos entre eles!

Aqui está uma resposta curta:

ballToBrick = ballPosition - brickPosition;
ballToBrick.Normalize();
brickFacing = Vector2(0,1).Normalize();


float angle = acos( Dot(ballToBrick, brickFacing) );

O revestimento do tijolo é um vetor complicado, é o "ponto inicial" do cálculo do ângulo. e se você quiser que o vetor aponte para cima, faça-o (0, 1), aponte para a esquerda (-1, 0), para a direita (1, 0), aponte para baixo (0, -1). Supondo que você esteja no eixo OpenGL, onde a direita e a direita são positivas.

Se você não sabe, aqui estão as definições de cada função usada:

Vector2.Normalize()
{
    float length = squareroot(x * x + y * y);
    x = x / length;
    y = y / length;
    return this;
}

Dot(Vector2 a, Vector2 b)
{
    return a.x * b.x + a.y * b.y;
}

( https://en.wikipedia.org/wiki/Dot_product )

Referência: http://blog.wolfire.com/2009/07/linear-algebra-for-game-developers-part-2/

Gustavo Maciel
fonte