Làm thế nào để xác định hướng va chạm giữa hai hình chữ nhật?


7

Tôi đang cố gắng tìm ra cách xác định hướng va chạm xảy ra giữa hai hình chữ nhật.

Một hình chữ nhật không di chuyển. Hình chữ nhật khác có vận tốc theo bất kỳ hướng nào. Khi xảy ra va chạm, tôi muốn có thể đặt vị trí của hình chữ nhật đang di chuyển đến điểm va chạm.

Tôi dường như bị mắc kẹt trong việc xác định từ hướng nào tác động xảy ra. Nếu tôi đang di chuyển nghiêm ngặt theo chiều dọc hoặc chiều ngang, tôi quản lý phát hiện tuyệt vời. Nhưng khi di chuyển theo cả hai hướng cùng một lúc, những điều kỳ lạ xảy ra.

Cách tốt nhất để xác định hướng va chạm xảy ra giữa hai hình chữ nhật là gì?


1
Làm thế nào bạn đang phát hiện va chạm?
MichaelHouse

3
Có vẻ như bạn đang cố xác định điểm ảnh hưởng. Nếu một hình chữ nhật đứng yên, bạn sẽ nghĩ rằng việc đảo ngược Vector chuyển động của hình chữ nhật đang di chuyển sẽ cho bạn "hướng va chạm"
John McDonald

Câu trả lời:


9

Tôi dường như bị mắc kẹt trong việc xác định từ hướng nào tác động xảy ra. Nếu tôi đang di chuyển nghiêm ngặt theo chiều dọc hoặc chiều ngang, tôi quản lý phát hiện tuyệt vời. Nhưng khi di chuyển theo cả hai hướng cùng một lúc, những điều kỳ lạ xảy ra.

tl; dr Giải pháp là di chuyển và kiểm tra va chạm một trục tại một thời điểm .

Tôi đã có vấn đề rất giống nhau. Tôi cá rằng giai đoạn cập nhật của vòng lặp trò chơi của bạn trông giống như thế này:

  • object.x + = object.vx
  • object.y + = object.vy
  • kiểm tra va chạm
  • trả lại va chạm

Mẹo ở đây là di chuyển kiểm tra va chạm một trục tại một thời điểm. Như bạn đã nói, "Nếu tôi di chuyển nghiêm ngặt theo chiều dọc hoặc chiều ngang, tôi quản lý phát hiện tuyệt vời." Vậy là bạn đã giải quyết được 99% vấn đề. Chỉ cần thay đổi logic của bạn để trông như thế này:

  • object.x + = object.vx
  • kiểm tra / trả lời va chạm
  • object.y + = object.vy
  • kiểm tra / trả lời va chạm

Trong các trường hợp đơn giản, không quan trọng bạn thực hiện trục nào trước. Nếu bạn không cảm thấy tốt khi chọn cái này hay cái kia một cách tùy tiện, thì việc kiểm tra trục đầu tiên trong đó vận tốc tuyệt đối của đối tượng là lớn nhất.


9

Theo câu trả lời của larsbutler, đối với các trường hợp đơn giản, việc bạn kiểm tra va chạm x hay y trước không thành vấn đề. Tuy nhiên, điều này có thể nhanh chóng dẫn đến sự thiếu chính xác, sau đó (đặc biệt là với hình dạng phức tạp hơn, vận tốc lớn hơn và nhiều vật thể hơn).

Nếu bất cứ ai quan tâm đến việc thực hiện một thuật toán phát hiện va chạm tinh vi hơn, thì đây là danh sách những điều cần thiết:

  1. Đầu tiên, thuật toán thực hiện quét và cắt tỉa để thu hẹp số lượng đối tượng cần kiểm tra. Nếu bạn đang kiểm tra mọi đối tượng chống lại mọi đối tượng khác , nó có thể khá tốn kém, tính toán. Về cơ bản, bạn dự đoán liệu một đối tượng có khả năng va chạm trong tương lai hay không; nếu nó không có khả năng, bạn không làm các phép tính.
  2. Sau khi cắt tỉa, bạn thực hiện kiểm tra va chạm sơ bộ. Mỗi đối tượng có một hình chữ nhật hoặc hình tròn giới hạn (một thứ dễ tính toán va chạm). Việc phát hiện xem hai hình tròn / hình chữ nhật có va chạm hay không khá đơn giản và có thể nhanh chóng loại bỏ các phép tính không cần thiết giữa hai đối tượng ở hai phía đối diện của màn hình.
  3. Nếu phát hiện sơ bộ đã được thực hiện, bạn cần lặp qua các cạnh của mỗi hình dạng và phát hiện bất kỳ điểm va chạm nào (giao điểm của hai đoạn đường). Trong trường hợp của Jon, đây sẽ là điểm va chạm trên trục tung và trục ngang.
  4. Khi bạn có một danh sách các điểm va chạm, bạn cần tính toán điểm va chạm chính xác . Có một số cách bạn có thể làm điều này, và tất cả phụ thuộc vào mức độ chính xác mà bạn muốn trở thành. Một lựa chọn là một nửa thặng dư thời gian (của bạn tích hợp vật lý ), tính toán lại vị trí của các hình dạng, và chạy lại phát hiện va chạm cho đến khi có chỉ có một điểm va chạm. Về cơ bản, bạn đang tính gần đúng "thời điểm tác động". Nếu mô phỏng của bạn không có nhiều lực khác biệt một phần, bạn chỉ có thể sử dụng vận tốc của tích hợp trước đó, với các nửa thời gian tiếp theo.
  5. Kết quả của bước bốn sẽ cung cấp cho bạn các điểm va chạm gần đúng (trong phạm vi giới hạn trên / dưới như 3px hoặc thứ gì đó). Nếu có nhiều hơn một điểm va chạm, bạn sẽ phải coi chúng là một cạnh tưởng tượng. Sau đó, bạn có thể thực hiện các tính toán độ phân giải va chạm (vận tốc, động lượng, ma sát, v.v.)

Hy vọng điều này sẽ giúp được ai đó.

Cụ thể cho câu hỏi của Jon:

Bước bạn thiếu của thuật toán va chạm là bước # 4. Theo những gì tôi hiểu, hình chữ nhật của bạn cắt nhau theo đường chéo và cuối cùng nhận được hai điểm va chạm (một theo chiều ngang và một theo chiều dọc). Xác định điểm va chạm nào xảy ra trước tiên thực sự phụ thuộc vào những gì bạn đang sử dụng để tích hợp vật lý.

Từ mô tả của bạn, có vẻ như các hình chữ nhật không xoay và những thứ như lực khác biệt một phần không đáng quan tâm lắm. Nếu đây là trường hợp, việc tìm ra cạnh nào va chạm đầu tiên là khá đơn giản. Đây là một số mã giả:

/*
   Assume Obj1 is stationary
   Assume Obj2's velocity is -x and -y (to bottom left)
   From this, we know the collision edges are:
*/
colEdgesObj1 = [1,0]; //right, top
colEdgesObj2 = [0,1]; //left, bottom
//... where [0=left/1=right, 0=top/1=bottom]

//Calculate distances between Obj1 edges and Obj2 edges
distX = Math.Abs(Obj1[colEdgesObj1[0] ? "right" : "left"] -
                 Obj2[colEdgesObj2[0] ? "right" : "left"]);
distY = Math.Abs(Obj1[colEdgesObj1[1] ? "bottom" : "top"] -
                 Obj2[colEdgesObj2[1] ? "bottom" : "top"]);

//Calculate time object would take to go those distances
//(assuming Obj2 is the only moving object)
timeX = distX/Obj2.VelX;
timeY = distY/Obj2.VelY;

//If time is greater, that axis has been colliding longer
if timeX > timeY
    //collided X axis first
else if timeY > timeX
    //collided Y axis first
else
    //collided at a corner
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.