Breakout-Kollision: Erkennen der Kollisionsseite

10

Ich schreibe einen Breakout-Klon (mein erstes Spiel) und bin völlig festgefahren, wie ich herausfinde, welche Seite des Ziegels getroffen wurde.

Ich habe eine Kollisionserkennungsmethode, die folgendermaßen aussieht:

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;  

Dies funktioniert völlig in Ordnung, aber ich muss die Seite der Kollision und die Position relativ zur Mitte kennen, um richtig reagieren zu können.

Ich habe die letzten Tage damit verbracht, herumzuschnüffeln, bin aber verloren.

user590903
quelle

Antworten:

13

Dies alles kann aus der Position der Kugel relativ zur Position des Ziegels, mit dem sie kollidierte, ermittelt werden.

Sobald Sie eine Kollision festgestellt haben:

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

Die ersten beiden prüfen, ob sich der Ball über oder unter dem Ziegel befindet. Wenn sich keiner von beiden neben dem Ziegel befinden muss, prüfen Sie, auf welcher Seite er sich befindet. Dies muss getweeked werden, um zu passen, wo Sie den Ort nehmen, dh ziegelposition ist die Mitte des Ziegels oder Ziegelposition ist die obere linke Ecke.

MichaelHouse
quelle
1
Aber wie würden Sie dies verwenden, um den Spieler neu zu positionieren, da sich der Spieler innerhalb eines Steins bewegt, werden mehrere dieser Bedingungen erfüllt, und wenn Sie das gewünschte x an den Rand der Wand zurücksetzen, zum Beispiel wenn es die Taste drückt Wenn ein Stein das gewünschte x genau neben die Wand setzt, funktioniert es nicht wirklich, denn wenn Sie die theoretische Position des Charakters überprüfen, um festzustellen, aus welcher Richtung er kollidiert, werden mehrere dieser Bedingungen erfüllt. Wie würden Sie also vorgehen? Verwenden Sie diese Option, um den Player zurückzusetzen. Müssen Sie am Ende jedes if) weitere hinzufügen?
Bluejayke
Soweit ich weiß, ist der "Spieler" in einem Breakout-Spiel das Paddel. Das Paddel bewegt sich weder innerhalb eines Ziegels, noch ändern Sie die Position des Paddels basierend auf der Interaktion des Balls mit Ziegeln. Wenn Sie dies tun, benötigen Sie keine zusätzliche Logik. Verarbeiten Sie die Neupositionierung erst, wenn Sie alle Kollisionsprüfungen durchgeführt haben. Oder kehren Sie zurück, sobald eine der Prüfungen wahr ist.
MichaelHouse
8

Sie können Vector Math verwenden, um die Winkel zwischen ihnen zu entdecken!

Hier ist eine kurze Antwort:

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


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

Die Ziegelverkleidung ist ein kniffliger Vektor, sie ist der "Startpunkt" der Winkelberechnung. und wenn Sie möchten, dass der Vektor nach oben zeigt, machen Sie ihn (0, 1), zeigen Sie nach links (-1, 0), nach rechts (1, 0), zeigen Sie nach unten (0, -1). Angenommen, Sie befinden sich in der OpenGL-Achse, in der oben und rechts positiv sind.

Wenn Sie es nicht wissen, finden Sie hier die Definitionen der verwendeten Funktionen:

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 )

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

Gustavo Maciel
quelle