một thuật toán va chạm hình chữ nhật 2D đơn giản cũng xác định các cạnh mà hình chữ nhật va chạm vào nhau?


16

Ban đầu tôi đã thử thực hiện giao lộ hình chữ nhật, hoạt động tốt. Tuy nhiên, khi tôi phải áp dụng hệ thống vật lý, chẳng hạn như vận tốc, gia tốc và vectơ định hướng, tôi sẽ phải tìm cách xác định phía nào của hình chữ nhật va chạm. Bây giờ, trong hệ thống của tôi, không có hình chữ nhật xoay, vì vậy điều này đã đơn giản hóa vấn đề. Tuy nhiên, tôi không thể tìm thấy một cách dễ dàng để xác định bên hình chữ nhật nào va chạm. Tôi đã từng đối phó với vấn đề này trước đây nhưng thất bại thảm hại.

Những gì tôi đã làm trong quá khứ là xác định khoảng cách giữa mỗi cạnh hình chữ nhật song song và kiểm tra xem khoảng cách có gần bằng 0 không (sử dụng một số khoảng cách được xác định ban đầu) hoặc là 0. Tuy nhiên, đối với số học dấu phẩy động, điều này chứng tỏ là không ổn định vì không rõ thời gian trôi qua. Đôi khi, các hình chữ nhật thực sự sẽ giao nhau trước khi nó đáp ứng phạm vi xác định.

Mặt khác, tôi đã suy nghĩ về việc sinh ra nhiều hình chữ nhật, mỗi hình chữ nhật cho mỗi bên. Tuy nhiên, sau khi suy nghĩ lại, nó sẽ giống như việc có một mặt song song với kiểm tra phạm vi khoảng cách, chỉ có phạm vi khoảng cách đó là chiều rộng của mỗi hình chữ nhật nhỏ.

Vì vậy, bất kỳ đề nghị cho vấn đề này?


Bạn đang sử dụng cập nhật vị trí rời rạc hoặc liên tục? (bạn có đang cập nhật vận tốc của mình bằng cách tăng tốc một lần mỗi khung hình và sau đó tính toán vị trí hoặc sử dụng chức năng để ngoại suy vị trí)
Casey Kuball

Câu trả lời:


24

Chuyển thể từ câu trả lời của tôi thành "Phía nào bị đánh?" :

Tôi đề nghị tính toán tổng số Minkowski của B và A, là một hình chữ nhật mới và kiểm tra vị trí trung tâm của hình chữ nhật A nằm tương đối với hình chữ nhật mới đó (để biết liệu có va chạm xảy ra hay không) và để biết nơi xảy ra va chạm đang xảy ra):

float w = 0.5 * (A.width() + B.width());
float h = 0.5 * (A.height() + B.height());
float dx = A.centerX() - B.centerX();
float dy = A.centerY() - B.centerY();

if (abs(dx) <= w && abs(dy) <= h)
{
    /* collision! */
    float wy = w * dy;
    float hx = h * dx;

    if (wy > hx)
        if (wy > -hx)
            /* collision at the top */
        else
            /* on the left */
    else
        if (wy > -hx)
            /* on the right */
        else
            /* at the bottom */
}

1
Tôi muốn thêm rằng 'trên cùng' và 'dưới cùng' có liên quan đến hệ thống tọa độ của bạn. Trong trò chơi của tôi chẳng hạn, (0,0) nằm ở trên cùng bên trái, vì vậy chúng được đảo ngược từ ví dụ của bạn. Chỉ là một thứ để ghi nhớ trong đầu.
Neikos

giải pháp tuyệt vời, làm việc rất tốt cho nhu cầu của tôi.
Opiatefuchs

1
Có một số trục trặc với dx trở thành 0 hoặc dy trở thành 0 hoặc cả hai? Hãy để tôi giải thích ... nếu dx = 0 && dy == 0, điều đó có nghĩa là cả hai hình chữ nhật đều có cùng nguồn gốc, thì thuật toán sẽ trả về đáy theo mặc định? nếu một trong hai là 0, thì kết quả đúng được mong đợi. Vì vậy, tôi nghĩ rằng, thuật toán này là chính xác, ngoại trừ trường hợp dx == 0 && dy == 0, không xác định được và không phải là đáy. Vì vậy, hãy cẩn thận và cảm ơn.
Prasanth

1
Bây giờ, tôi đã tự hỏi điều gì xảy ra khi dx == dy, w == h ... sau đó, mã quyết định rằng kết quả là một phía khi nó thực sự không xác định..imagine hai hình vuông giao nhau sao cho tâm của một hình vuông nằm ở một góc của một hình vuông khác và trung tâm của hình vuông khác nằm ở góc của hình vuông đầu tiên. Ở đây, bên nên không xác định - nó không phải là bên phải hoặc dưới cùng. Đó là cả hai?!
Prasanth
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.