Dapatkan detail tabrakan dari Rectangle.Intersects ()

9

Saya memiliki permainan Breakout di mana, pada titik tertentu, saya mendeteksi tabrakan antara bola dan dayung dengan sesuatu seperti ini:

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

Apakah ada cara saya bisa mendapatkan koordinat yang tepat dari tabrakan, atau rincian tentang hal itu, dengan arus XNA API?

Saya berpikir untuk melakukan beberapa perhitungan dasar, seperti membandingkan koordinat yang tepat dari setiap objek pada saat tabrakan. Akan terlihat seperti ini:

// 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

Tapi saya tidak yakin ini cara yang benar untuk melakukannya.

Apakah kalian punya tips tentang mungkin mesin yang mungkin harus saya gunakan untuk mencapai itu? Atau bahkan praktik pengkodean yang baik menggunakan metode ini?

Daniel Ribeiro
sumber

Jawaban:

8

Persegi panjang XNA sangat terbatas. The Rectangle.Intersects()Metode hanya mengembalikan hasil boolean, sehingga Anda akan perlu melakukan lebih banyak tes sendiri jika Anda ingin detail. Anda bisa, bagaimanapun, menggunakan Rectangle.Intersect(Rectangle, Rectangle)metode untuk mendapatkan persegi panjang di mana keduanya tumpang tindih. Itu akan memberi Anda beberapa informasi tentang kedalaman dan lokasi, setidaknya.

ssb
sumber
Apakah get the rectangle where the two overlapfungsi ini tersedia di XNA APIatau saya harus mengunduh beberapa hal tambahan, seperti Platformer Starter Kit?
Daniel Ribeiro
1
Metode apa ini? Saya tidak ingat bahwa XNA 4.0 mendukung Rectangle Rectangle.Intersects(...).
ashes999
Seseorang memberi saya hak di stackoverflow: msdn.microsoft.com/en-us/library/…
Daniel Ribeiro
Ok, dengan Rectangle yang dikembalikan, bagaimana saya bisa mengecek posisi dayung yang terbentur oleh bola?
Daniel Ribeiro
Jika Anda tahu bahwa pemukul dan bola yang berpotongan maka Anda menggunakan informasi lokasi dari persegi panjang dayung yang Anda diperiksa di tempat pertama, yaitu rectangle.Xatau rectangle.Yatau apa pun yang ingin Anda akses.
ssb
4

Pembaruan: Jika Anda menggunakan MonoGame, maka pada 3.0 beta, Rectangle Rectangle.Intersect(rectangle, rectangle)tidak ada. Anda dapat menggunakan kode di bawah ini dari kit XNA Platformer sebagai gantinya.


Anda dapat mengunduh XNA Platformer Starter Kit ( porting ke Windows 7 ). Ini dikirimkan dengan metode ekstensi helper yang mengembalikan persegi panjang yang menggambarkan persimpangan dua persegi panjang:

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);
        }
}
ashes999
sumber
Terima kasih banyak atas tautan ini. Bolehkah saya bertanya mengapa Anda perlu menggunakan versi yang dimodifikasi? Apakah port itu resmi?
Daniel Ribeiro
@DanielRibeiro Saya memeriksa riwayat saya dan ternyata saya tidak memodifikasinya. Pelabuhan tidak resmi; Saya tidak dapat menemukan yang asli. Ini bekerja dengan MonoGame / C #, yang cukup bagus untuk saya.
ashes999
Tetapi ada port asli, kan? Bukankah ini seharusnya fitur yang begitu sederhana? Ngomong-ngomong, saya tidak menggunakan MonoGame, hanya XNA. Apakah Anda masih merekomendasikan saya untuk menggunakan port ini?
Daniel Ribeiro
Saya harus mengatur jawaban yang benar ssb, tetapi terima kasih banyak untuk ini. Saya pasti akan masuk ke port ini! Terimakasih banyak!
Daniel Ribeiro
1
@DanielRibeiro ah, begitu. Saya pikir metode itu tidak ada di MonoGame, itulah sebabnya saya akhirnya menggunakan pendekatan ini. Cheers though.
ashes999