Breakout Collision: detección del lado de la colisión

10

Estoy escribiendo un clon de ruptura (mi primer juego) y estoy totalmente atascado en cuanto a cómo averiguar qué lado del ladrillo fue golpeado.

Tengo un método de detección de colisión que se ve así:

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;  

Esto funciona totalmente bien, pero necesito saber el lado de la colisión y la ubicación relativa al centro para poder responder adecuadamente.

He pasado los últimos días husmeando pero estoy perdido.

usuario590903
fuente

Respuestas:

13

Todo esto se puede recoger desde la posición de la pelota en relación con la posición del ladrillo con el que colisionó.

Una vez que haya detectado una colisión:

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

Los dos primeros verifican si la pelota está arriba o debajo del ladrillo. Si ninguno de los dos debe estar al lado del ladrillo, compruebe de qué lado está. Será necesario ajustarlo para que coincida con el lugar desde donde toma la ubicación, es decir, brickPosition es el centro del ladrillo o brickPosition es la esquina superior izquierda.

MichaelHouse
fuente
1
Pero, ¿cómo usaría esto para reposicionar al jugador, ya que si el jugador se mueve dentro de un ladrillo, se cumplirán varias de esas condiciones, y si restablece la x deseada al borde de la pared, por ejemplo, si presiona la tecla de un ladrillo establece la x deseada exactamente al lado de la pared, entonces realmente no funcionaría porque cuando verifica la posición teórica del personaje para ver desde qué dirección está colisionando, se cumplirán varias de estas condiciones, entonces, ¿cómo podría use esto para reiniciar el reproductor, ¿necesita agregar otros al final de cada if)?
bluejayke
Hasta donde yo sé, el "jugador" en un juego tipo breakout es el remo. La pala no se mueve dentro de un ladrillo, ni está cambiando la posición de la pala en función de la interacción de la pelota con los ladrillos. Si eso es lo que está haciendo, no necesita lógica adicional, simplemente no procese la reposición hasta que haya realizado todas las comprobaciones de colisión. O regrese una vez que uno de los cheques sea verdadero.
MichaelHouse
8

¡Podrías usar Vector Math para descubrir los ángulos entre ellos!

Aquí hay una respuesta corta:

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


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

El revestimiento de ladrillo es un vector complicado, es el "punto de inicio" del cálculo del ángulo. y si desea que el vector apunte hacia arriba, hágalo (0, 1), apunte a la izquierda (-1, 0), a la derecha (1, 0), apunte hacia abajo (0, -1). Suponiendo que está en el eje OpenGL, donde arriba y derecha son positivas.

Si no sabe, aquí están las definiciones de cada función utilizada:

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 )

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

Gustavo Maciel
fuente