Bị mắc kẹt trong tường sau khi va chạm hộp hình chữ nhật


7

Sử dụng XNA được tích hợp trong Intersects () trên hai Hình chữ nhật, tôi có thể phát hiện va chạm và đặt vận tốc của mình bằng không. Tuy nhiên, đối tượng bị mắc kẹt ở đó và không thể thoát ra! Làm thế nào tôi có thể giải quyết vụ va chạm này đúng cách?

Câu trả lời:


12

Điều này là do một khi đối tượng của bạn vào tường và bạn tìm thấy sự va chạm, bạn chỉ cần dừng chuyển động của đối tượng bằng cách đặt vận tốc của nó về 0, nhưng đối tượng vẫn ở trong bức tường đó.

Để khắc phục, bạn phải giải quyết va chạm bằng cách di chuyển đối tượng. Bạn có hai lựa chọn ở đây:

  • Di chuyển đối tượng trở lại vị trí cũ của nó, bằng cách áp dụng ngược lại vận tốc để hủy bỏ chuyển động ngay khi bạn phát hiện va chạm. Ưu điểm: cực kỳ dễ thực hiện. Nếu nó không ảnh hưởng đến trò chơi của bạn, hãy sử dụng tùy chọn này. Nhược điểm: Điều này sẽ ngăn đối tượng di chuyển theo bất kỳ hướng nào có thể gây ra va chạm (ví dụ như bạn sẽ không thể trượt dọc theo một bức tường).
  • Tìm từ nơi đối tượng và giải quyết va chạm cho phù hợp. Ví dụ, nếu đối tượng đến từ bên trái và va chạm vào bên trái của bức tường, bạn chỉ cần di chuyển đối tượng ngay bên trái của bức tường. Bằng cách lặp lại điều này cho tất cả các cạnh của hình chữ nhật, đối tượng sẽ được phép tiếp tục di chuyển về phía vận tốc mong muốn của mình nhưng vẫn tránh được va chạm.

Thực hiện tùy chọn thứ hai

Ở đây tôi sẽ giả sử rằng vận tốc thể hiện hướng mà vật thể đang đi (về cơ bản là bạn không thay đổi vận tốc giữa thay đổi vị trí của vật thể và kiểm tra va chạm). Tôi cũng sẽ cho rằng nguồn gốc của bạn được đặt ở phía trên bên trái của hình ảnh (vì vậy khi di chuyển đối tượng để giải quyết va chạm, tôi sẽ định vị góc trên cùng bên trái).

Đây là cách tôi sẽ làm:

if (objRect.Intersects(wallRect)) // If there is a collision
{
    Vector2 newPos = obj.Position;

    if (obj.Velocity.X > 0) // object came from the left
        newPos.X = wallRect.Left - objRect.Width;
    else if (obj.Velocity.X < 0) // object came from the right
        newPos.X = wallRect.Right;
    if (obj.Velocity.Y > 0) // object came from the top
        newPos.Y = wallRect.Top - objRect.Height;
    else if (obj.Velocity.Y < 0) // object came from the bottom
        newPos.Y = wallRect.Bottom;

    obj.Position = newPos;
}

Bạn cũng có thể sử dụng vị trí của đối tượng cũ để tìm vị trí của đối tượng, nhưng sử dụng vận tốc đơn giản hơn trong trường hợp này.


Được rồi, vì vậy về cơ bản nó bị mắc kẹt trong tường và vụ va chạm đang tiếp tục. Làm thế nào tôi sẽ đi về giải quyết điều này mặc dù?
Jopo

Đã chỉnh sửa nó như bạn yêu cầu. Bạn có muốn một số mẫu mã để hiển thị cả hai tùy chọn sẽ được thực hiện như thế nào không?
Jesse Emond

Tôi đã thử thực hiện cái đầu tiên trước đó bằng cách thực hiện một vectơ gọi là hướng là vectơ chuẩn hóa với trái hoặc phải tùy thuộc vào phím được nhấn, sau đó tôi nhân nó với vận tốc khi phát hiện va chạm. Điều này làm việc trên hầu hết các phần, nhưng nó dường như chỉ hoạt động ở một bên của hình chữ nhật (bên phải?). Đối với phần thứ hai, tôi sẽ đánh giá cao một mẫu mã vì tôi đã nghe nhiều về điều này nhưng chưa thấy bất kỳ triển khai cụ thể nào.
Jopo

1
Tùy chọn đầu tiên của bạn nên là một ví dụ về những việc không nên làm. Bất kỳ trò chơi với loại phát hiện va chạm đó, tôi sẽ xem xét khiếm khuyết.
Tấn

1
Tại sao câu trả lời này không được chấp nhận nếu bạn quản lý để thực hiện phương pháp đã cho và nó đã hoạt động?
Jonathan Connell

1

Bạn có thể làm điều này theo nhiều cách khác nhau.

Một phương pháp là lưu trữ vị trí trước đó của Hình chữ nhật mỗi khung. Vì vậy, khi hình chữ nhật của bạn Giao nhau, chỉ cần đặt vị trí đối tượng thành vị trí cũ không va chạm. Phương pháp này không phải là tốt nhất, vì nếu tốc độ Hình chữ nhật cao, bạn có thể thấy vị trí mà bạn đã thực hiện thông qua mã.

Một phương pháp khác là kiểm tra sự va chạm với Raycast, vì vậy bạn có thể xem trước một vụ va chạm trước khi nó xảy ra.

Hãy xem msDN để biết tài liệu về vụ va chạm Raycast và bạn sẽ có thể làm điều đó.

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.