Nhận chi tiết va chạm từ hình chữ nhật.Intersects ()


9

Tôi có một trò chơi Breakout, tại một số điểm, tôi phát hiện ra sự va chạm giữa quả bóng và mái chèo với thứ gì đó như thế này:

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

Có cách nào để tôi có thể có được tọa độ chính xác của vụ va chạm, hoặc bất kỳ chi tiết nào về nó, với hiện tại XNA APIkhông?

Tôi đã nghĩ đến việc thực hiện một số tính toán cơ bản, chẳng hạn như so sánh tọa độ chính xác của từng đối tượng vào thời điểm va chạm. Nó sẽ trông giống như thế này:

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

Nhưng tôi không chắc đây là cách chính xác để làm điều đó.

Các bạn có bất cứ lời khuyên về có thể một động cơ tôi có thể phải sử dụng để đạt được điều đó? Hoặc thậm chí thực hành mã hóa tốt bằng phương pháp này?

Câu trả lời:


8

Hình chữ nhật của XNA khá hạn chế. Các Rectangle.Intersects()phương pháp duy nhất trả về một kết quả boolean, vì vậy bạn sẽ cần phải làm thêm các xét nghiệm cho mình nếu bạn muốn biết chi tiết. Tuy nhiên, bạn có thể sử dụng Rectangle.Intersect(Rectangle, Rectangle)phương thức để có được hình chữ nhật trong đó hai hình trùng nhau. Điều đó sẽ cung cấp cho bạn một số thông tin về độ sâu và vị trí, ít nhất.


get the rectangle where the two overlapchức năng này có sẵn trên XNA APIhoặc tôi phải tải xuống một số nội dung bổ sung, như Platformer Starter Kit?
Daniel Ribeiro

1
Phương pháp này là gì? Tôi không nhớ rằng XNA 4.0 hỗ trợ Rectangle Rectangle.Intersects(...).
tro999

Ai đó đã cho tôi quyền tại stackoverflow: msdn.microsoft.com/en-us/l Library / Fiêu
Daniel Ribeiro

Ok, với hình chữ nhật được trả về, làm thế nào tôi có thể kiểm tra vị trí của mái chèo bị va chạm bởi quả bóng?
Daniel Ribeiro

Nếu bạn biết rằng mái chèo và bóng được giao nhau sau đó bạn sử dụng thông tin vị trí của hình chữ nhật mái chèo mà bạn kiểm tra ở nơi đầu tiên, tức là rectangle.Xhoặc rectangle.Yhoặc bất cứ điều gì bạn muốn truy cập.
ssb

4

Cập nhật: Nếu bạn đang sử dụng MonoGame, thì đến phiên bản 3.0 beta, Rectangle Rectangle.Intersect(rectangle, rectangle)không tồn tại. Thay vào đó, bạn có thể sử dụng mã dưới đây từ bộ XNA Platformer.


Bạn có thể tải xuống Bộ khởi động XNA Platformer ( được chuyển sang Windows 7 ). Nó vận chuyển với một phương thức mở rộng của trình trợ giúp trả về một hình chữ nhật mô tả giao điểm của hai hình chữ nhật:

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

Cảm ơn bạn rất nhiều cho liên kết này. Tôi có thể hỏi bạn tại sao bạn cần sử dụng một phiên bản sửa đổi? Là cảng chính thức?
Daniel Ribeiro

@DanielRibeiro Tôi đã kiểm tra lịch sử của mình và dường như tôi đã không sửa đổi nó sau tất cả. Cảng là không chính thức; Tôi chỉ đơn giản là không thể tìm thấy bản gốc. Nó hoạt động với MonoGame / C #, đủ tốt cho tôi.
tro999

Nhưng có một cổng ban đầu, phải không? Đây không phải là một tính năng đơn giản như vậy sao? Dù sao, tôi không sử dụng MonoGame, chỉ là XNA. Bạn vẫn sẽ đề nghị tôi sử dụng cổng này chứ?
Daniel Ribeiro

Tôi đã phải đặt câu trả lời chính xác ssb, nhưng cảm ơn bạn rất nhiều vì điều này. Tôi chắc chắn sẽ vào cảng này! Cảm ơn nhiều!
Daniel Ribeiro

1
@DanielRibeiro ah, tôi hiểu rồi. Tôi nghĩ rằng phương pháp đó không tồn tại trong MonoGame, đó là lý do tại sao tôi đã kết thúc bằng cách sử dụng phương pháp này. Chúc mừng mặc dù.
tro999
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.