รับรายละเอียดการชนจาก Rectangle.Intersects ()


9

ฉันมีเกมฝ่าวงล้อมที่บางจุดฉันตรวจพบการชนกันระหว่างลูกบอลและไม้พายด้วยสิ่งนี้:

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

มีวิธีที่ฉันจะได้รับพิกัดที่แน่นอนของการปะทะกันหรือรายละเอียดใด ๆ เกี่ยวกับเรื่องนี้ด้วยการใด ๆ ในปัจจุบันXNA API?

ฉันคิดถึงการคำนวณพื้นฐานบางอย่างเช่นการเปรียบเทียบพิกัดที่แน่นอนของแต่ละวัตถุในช่วงเวลาของการชน มันจะมีลักษณะเช่นนี้:

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

แต่ฉันไม่แน่ใจว่านี่เป็นวิธีที่ถูกต้องที่จะทำ

พวกคุณมีเคล็ดลับเกี่ยวกับเครื่องยนต์ที่ฉันอาจต้องใช้เพื่อให้บรรลุหรือไม่? หรือแม้แต่การเขียนโค้ดที่ดีโดยใช้วิธีนี้?

คำตอบ:


8

สี่เหลี่ยมของ XNA ค่อนข้าง จำกัด Rectangle.Intersects()วิธีเดียวที่ส่งกลับผลบูลดังนั้นคุณจะต้องทำมากขึ้นการทดสอบตัวเองถ้าคุณต้องการรายละเอียด อย่างไรก็ตามคุณสามารถใช้Rectangle.Intersect(Rectangle, Rectangle)วิธีการรับสี่เหลี่ยมที่สองทับซ้อนกัน อย่างน้อยจะให้ข้อมูลเกี่ยวกับความลึกและตำแหน่ง


get the rectangle where the two overlapfunctionallity นี้มีอยู่ในXNA APIหรือฉันต้องดาวน์โหลดบางสิ่งเพิ่มเติมเช่นPlatformer Starter Kit?
Daniel Ribeiro

1
วิธีนี้คืออะไร? ผมจำไม่ได้ว่า XNA 4.0 Rectangle Rectangle.Intersects(...)สนับสนุน
ashes999

มีคนให้สิทธิ์ฉันที่ stackoverflow: msdn.microsoft.com/en-us/library/…
Daniel Ribeiro

โอเคกับสี่เหลี่ยมผืนผ้าที่คืนมาฉันจะตรวจสอบตำแหน่งของไม้ตีที่ลูกบอลชนกันได้อย่างไร
Daniel Ribeiro

ถ้าคุณรู้ว่าพายและลูกจะถูกตัดแล้วคุณใช้ข้อมูลสถานที่ตั้งของรูปสี่เหลี่ยมผืนผ้าพายที่คุณตรวจสอบในสถานที่แรกคือrectangle.Xหรือrectangle.Yหรือสิ่งที่คุณต้องการที่จะเข้าถึง
ssb

4

อัปเดต:หากคุณใช้ MonoGame แสดงว่าเป็นรุ่นเบต้า 3.0 Rectangle Rectangle.Intersect(rectangle, rectangle)ไม่มีอยู่จริง คุณสามารถใช้รหัสด้านล่างจากชุด XNA Platformer แทน


คุณสามารถดาวน์โหลด XNA Platformer Starter Kit (เชื่อมต่อกับ Windows 7 ) มันมาพร้อมกับวิธีการขยายผู้ช่วยที่ส่งกลับสี่เหลี่ยมผืนผ้าที่อธิบายถึงจุดตัดของสองสี่เหลี่ยม:

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);
        }
}

ขอบคุณมากสำหรับลิงค์นี้ ฉันขอถามคุณได้ไหมว่าทำไมคุณถึงต้องใช้รุ่นที่ได้รับการแก้ไข นั่นพอร์ตทางการหรือไม่
Daniel Ribeiro

@DanielRibeiro ฉันตรวจสอบประวัติของฉันและฉันไม่ได้ทำการแก้ไข พอร์ตไม่เป็นทางการ ฉันหาต้นฉบับไม่เจอ มันใช้งานได้กับ MonoGame / C # ซึ่งดีพอสำหรับฉัน
ashes999

แต่มีพอร์ตดั้งเดิมใช่ไหม สิ่งนี้ไม่ควรจะเป็นคุณสมบัติที่เรียบง่ายใช่ไหม อย่างไรก็ตามฉันไม่ได้ใช้ MonoGame แค่ XNA คุณยังแนะนำให้ฉันใช้พอร์ตนี้หรือไม่?
Daniel Ribeiro

ฉันต้องตั้งคำตอบให้ถูกต้องssbแต่ขอบคุณมากสำหรับสิ่งนี้ ฉันจะไปที่ท่าเรือนี้แน่นอน! ขอบคุณมาก!
Daniel Ribeiro

1
@DanielRibeiro อ่าฉันเข้าใจแล้ว ฉันคิดว่าวิธีการนี้ไม่มีอยู่ใน MonoGame ซึ่งเป็นสาเหตุที่ฉันลงเอยด้วยการใช้วิธีการนี้ ไชโย
ashes999
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.