Ví dụ về Nền tảng Microsoft XNA, Phát hiện Collsion có được triển khai chính xác không?


11

Ví dụ được cung cấp bởi Microsoft dường như nếu phát hiện va chạm (từ những gì tôi có thể thấy) sẽ có một lỗi nhỏ. Khi người dùng va chạm với một ô Không thể vượt qua, độ sâu của giao lộ được tính toán. Giá trị độ sâu X và Y nhỏ hơn được sử dụng để cố định vị trí của người dùng để nó không còn va chạm với ô. Nhưng nếu người dùng đang di chuyển theo đường chéo thì điều này có thể dẫn đến việc người dùng không kết thúc chính xác tại điểm mà nhân vật sẽ va chạm đầu tiên với gạch không?

Tôi có thể sai nhưng đó chỉ là cách tôi nhìn thấy nó.

   private void HandleCollisions()
        {
            // Get the player's bounding rectangle and find neighboring tiles.
            Rectangle bounds = BoundingRectangle;
            int leftTile = (int)Math.Floor((float)bounds.Left / Tile.Width);
            int rightTile = (int)Math.Ceiling(((float)bounds.Right / Tile.Width)) - 1;
            int topTile = (int)Math.Floor((float)bounds.Top / Tile.Height);
            int bottomTile = (int)Math.Ceiling(((float)bounds.Bottom / Tile.Height)) - 1;

            // Reset flag to search for ground collision.
            isOnGround = false;

            // For each potentially colliding tile,
            for (int y = topTile; y <= bottomTile; ++y)
            {
                for (int x = leftTile; x <= rightTile; ++x)
                {
                    // If this tile is collidable,
                    TileCollision collision = Level.GetCollision(x, y);
                    if (collision != TileCollision.Passable)
                    {
                        // Determine collision depth (with direction) and magnitude.
                        Rectangle tileBounds = Level.GetBounds(x, y);
                        Vector2 depth = RectangleExtensions.GetIntersectionDepth(bounds, tileBounds);
                        if (depth != Vector2.Zero)
                        {
                            float absDepthX = Math.Abs(depth.X);
                            float absDepthY = Math.Abs(depth.Y);

                            // Resolve the collision along the shallow axis.
                            if (absDepthY < absDepthX || collision == TileCollision.Platform)
                            {
                                // If we crossed the top of a tile, we are on the ground.
                                if (previousBottom <= tileBounds.Top)
                                    isOnGround = true;

                                // Ignore platforms, unless we are on the ground.
                                if (collision == TileCollision.Impassable || IsOnGround)
                                {
                                    // Resolve the collision along the Y axis.
                                    Position = new Vector2(Position.X, Position.Y + depth.Y);

                                    // Perform further collisions with the new bounds.
                                    bounds = BoundingRectangle;
                                }
                            }
                            else if (collision == TileCollision.Impassable) // Ignore platforms.
                            {
                                // Resolve the collision along the X axis.
                                Position = new Vector2(Position.X + depth.X, Position.Y);

                                // Perform further collisions with the new bounds.
                                bounds = BoundingRectangle;
                            }
                        }
                    }
                }
            }

            // Save the new bounds bottom.
            previousBottom = bounds.Bottom;
        }

3
Tại sao trừ 1, ppl? Câu hỏi có giá trị đối với tôi. Nhưng đây là một câu trả lời ngắn gọn: Bản demo nền tảng đi kèm với XNA chỉ là một ví dụ. Không được tuân thủ nghiêm ngặt như là một mô hình cho các trò chơi của bạn. Đó là để cho bạn thấy rằng một trò chơi CÓ THỂ được thực hiện. Bạn không nên bận tâm nếu việc thực hiện nó không phải là tốt nhất.
Gustavo Maciel

Cảm ơn, tôi chỉ giả sử với ví dụ rằng những gì họ đã làm là cách tốt nhất để làm và tôi đang thiếu một cái gì đó. Cảm ơn đã xóa nó cho tôi.
PriestVallon

Câu trả lời:


12

Bạn hoàn toàn đúng . Tôi đã chia sẻ các vấn đề của mình với các thói quen va chạm trên mẫu nền tảng XNA. Nhưng tôi đã quản lý để bắt đầu từ mã như được cung cấp trong mẫu và sửa đổi nó một chút cho đến khi tôi đạt được kết quả nhất quán trong mọi kịch bản thử nghiệm mà tôi có thể đưa ra.

Cụ thể, loại vấn đề tôi gặp phải là khi cố gắng trượt dọc theo một bức tường bằng cách di chuyển theo đường chéo với nó. Do giả định mẫu tạo ra để giải quyết va chạm dựa trên trục dịch chuyển nhỏ nhất, điều này dẫn đến việc nhân vật không thể di chuyển khi đẩy vào tường theo một hướng nào đó. Chẳng hạn, sử dụng một dấu hiệu, tôi sẽ bị kẹt khi ôm trần nhà và cố gắng di chuyển từ trái sang phải (không thể nhớ chi tiết cụ thể). Chuyển đổi dấu hiệu sẽ giải quyết tình huống đó nhưng một vấn đề sẽ xuất hiện trong kịch bản ngược lại. Điểm mấu chốt là với việc triển khai được cung cấp, tôi không thể làm cho nó hoạt động chính xác ở mọi phía và từ mọi hướng - nó sẽ luôn thất bại trong ít nhất một trường hợp.

Vì vậy, cốt lõi của những thay đổi tôi đã làm là bắt đầu xử lý chuyển động trên trục X một cách độc lập với chuyển động trên trục Y, theo hai bước riêng biệt. Tôi đã viết về nó trước đây trong câu trả lời này vì vậy hãy đến đó để biết chi tiết.

Và nếu tôi nhớ chính xác, lý do thực sự của nó là như thế này:

nhập mô tả hình ảnh ở đây


1
David luôn luôn quan tâm đến XNA!
Gustavo Maciel

1
@ Gustavo-Gtoknu Tôi cảm thấy vẫn cần một bản vẽ của vấn đề: P
David Gouveia

1
Chỉ cần bắt gặp câu trả lời này - công việc tuyệt vời! Cảm ơn David.
Austin Brunkhorst

1

Khi bạn có nhiều va chạm nếu bạn khắc phục các va chạm của mình từ gần nhất đến xa nhất từ ​​trung tâm của mỗi hình chữ nhật có liên quan, bạn sẽ không gặp phải vấn đề "treo".

1) Tìm tất cả các hình chữ nhật va chạm

2) Nếu có nhiều hơn một (tùy theo trường hợp sử dụng của bạn, điều này có thể xảy ra thường xuyên hoặc không thường xuyên), hãy tìm gần nhất.

3) Giải quyết các va chạm một lần và kiểm tra xem các va chạm khác có còn hợp lệ không

Trong câu trả lời được chấp nhận, va chạm và logic đầu vào là bùn; nó có các kiểm tra để xác định tiêu đề, v.v. Việc thực hiện nó theo cách được mô tả sẽ giữ logic va chạm tách biệt với logic đầu vào với chi phí tính khoảng cách khi cần thiết.

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.