Holen Sie sich Kollisionsdetails von Rectangle.Intersects ()

9

Ich habe ein Breakout-Spiel, in dem ich irgendwann die Kollision zwischen Ball und Paddel mit so etwas erkenne:

// Ball class
rectangle.Intersects(paddle.Rectangle);

Gibt es eine Möglichkeit, die genauen Koordinaten der Kollision oder Einzelheiten dazu mit dem Strom zu ermitteln XNA API?

Ich dachte daran, einige grundlegende Berechnungen durchzuführen, beispielsweise den Vergleich der genauen Koordinaten jedes Objekts zum Zeitpunkt der Kollision. Es würde ungefähr so ​​aussehen:

// Ball class
if((rectangle.X - paddle.Rectangle.X) < (paddle.Rectangle.Width / 2))
    // Collision happened on the left side
else
    // Collision happened on the right side

Aber ich bin mir nicht sicher, ob dies der richtige Weg ist.

Habt ihr Tipps zu einem Motor, den ich verwenden muss, um das zu erreichen? Oder sogar gute Codierungspraktiken mit dieser Methode?

Daniel Ribeiro
quelle

Antworten:

8

Die Rechtecke von XNA sind ziemlich begrenzt. Die Rectangle.Intersects()Methode gibt nur ein boolesches Ergebnis zurück, sodass Sie selbst weitere Tests durchführen müssen, wenn Sie Details wünschen. Sie können jedoch die Rectangle.Intersect(Rectangle, Rectangle)Methode verwenden, um das Rechteck zu erhalten, in dem sich die beiden überlappen. Das gibt Ihnen zumindest einige Informationen über Tiefe und Position.

ssb
quelle
Ist diese get the rectangle where the two overlapFunktionalität auf dem verfügbar XNA APIoder muss ich einige zusätzliche Dinge herunterladen, wie z Platformer Starter Kit.
Daniel Ribeiro
1
Welche Methode ist das? Ich erinnere mich nicht, dass XNA 4.0 unterstützt Rectangle Rectangle.Intersects(...).
Asche999
Jemand gab mir das Recht bei stackoverflow: msdn.microsoft.com/en-us/library/…
Daniel Ribeiro
Ok, wie kann ich mit dem zurückgegebenen Rechteck die Position des Paddels überprüfen, das vom Ball kollidiert wurde?
Daniel Ribeiro
Wenn Sie wissen , dass das Paddel und Ball schneiden sich dann verwenden Sie die Standortinformationen des Paddels Rechteck , dass Sie in erster Linie geprüft, dh rectangle.Xoder rectangle.Yoder was auch immer Sie zugreifen möchten.
SSB
4

Update: Wenn Sie MonoGame verwenden, gibt es ab Version 3.0 Beta Rectangle Rectangle.Intersect(rectangle, rectangle)nicht mehr. Sie können stattdessen den folgenden Code aus dem XNA Platformer-Kit verwenden.


Sie können das XNA Platformer Starter Kit ( portiert auf Windows 7 ) herunterladen . Es wird mit einer Hilfserweiterungsmethode geliefert, die ein Rechteck zurückgibt, das den Schnittpunkt zweier Rechtecke beschreibt:

static class RectangleExtensions
    {
        /// <summary>
        /// Calculates the signed depth of intersection between two rectangles.
        /// </summary>
        /// <returns>
        /// The amount of overlap between two intersecting rectangles. These
        /// depth values can be negative depending on which wides the rectangles
        /// intersect. This allows callers to determine the correct direction
        /// to push objects in order to resolve collisions.
        /// If the rectangles are not intersecting, Vector2.Zero is returned.
        /// </returns>
        public static Vector2 GetIntersectionDepth(this Rectangle rectA, Rectangle rectB)
        {
            // Calculate half sizes.
            float halfWidthA = rectA.Width / 2.0f;
            float halfHeightA = rectA.Height / 2.0f;
            float halfWidthB = rectB.Width / 2.0f;
            float halfHeightB = rectB.Height / 2.0f;

            // Calculate centers.
            Vector2 centerA = new Vector2(rectA.Left + halfWidthA, rectA.Top + halfHeightA);
            Vector2 centerB = new Vector2(rectB.Left + halfWidthB, rectB.Top + halfHeightB);

            // Calculate current and minimum-non-intersecting distances between centers.
            float distanceX = centerA.X - centerB.X;
            float distanceY = centerA.Y - centerB.Y;
            float minDistanceX = halfWidthA + halfWidthB;
            float minDistanceY = halfHeightA + halfHeightB;

            // If we are not intersecting at all, return (0, 0).
            if (Math.Abs(distanceX) >= minDistanceX || Math.Abs(distanceY) >= minDistanceY)
                return Vector2.Zero;

            // Calculate and return intersection depths.
            float depthX = distanceX > 0 ? minDistanceX - distanceX : -minDistanceX - distanceX;
            float depthY = distanceY > 0 ? minDistanceY - distanceY : -minDistanceY - distanceY;
            return new Vector2(depthX, depthY);
        }

        /// <summary>
        /// Gets the position of the center of the bottom edge of the rectangle.
        /// </summary>
        public static Vector2 GetBottomCenter(this Rectangle rect)
        {
            return new Vector2(rect.X + rect.Width / 2.0f, rect.Bottom);
        }
}
Asche999
quelle
Vielen Dank für diesen Link. Darf ich Sie fragen, warum Sie eine modifizierte Version verwenden mussten? Ist dieser Hafen offiziell?
Daniel Ribeiro
@ DanielRibeiro Ich habe meinen Verlauf überprüft und ihn anscheinend doch nicht geändert. Der Hafen ist inoffiziell; Ich konnte das Original einfach nicht finden. Es funktioniert mit MonoGame / C #, was für mich gut genug war.
Asche999
Aber es gibt einen originalen Hafen, oder? Soll das nicht so einfach sein? Wie auch immer, ich benutze kein MonoGame, nur XNA. Würden Sie mir trotzdem empfehlen, diesen Port zu verwenden?
Daniel Ribeiro
Ich musste die richtige Antwort geben ssb, aber vielen Dank dafür. Ich werde auf jeden Fall in diesen Hafen einsteigen! Danke vielmals!
Daniel Ribeiro
1
@ DanielRibeiro ah, ich verstehe. Ich denke, dass diese Methode in MonoGame nicht existiert, weshalb ich diesen Ansatz verwendet habe. Prost aber.
Asche999