Sử dụng tổng số Minkowski
Một cách tốt để giải quyết vấn đề này là xem xét giao điểm giữa một đường chuyển động ( v ) được dịch sang gốc ( v ' ) và tổng số Minkowski của A xoay 180 độ tại điểm gốc ( A' ) và các chướng ngại vật của nó (chỉ B trong trường hợp này): A' ⊕ B .
Trong hình sau đây, tôi đặt một smack-dab trong nguồn gốc của một hệ tọa độ tùy ý. Điều này đơn giản hóa sự hiểu biết khi xoay A 180 độ kết quả trong A ' và v được dịch sang gốc bằng v' .
Tổng số Minkowski là hình chữ nhật màu xanh lá cây, và các điểm giao nhau của A di chuyển và B cố định có thể được tìm thấy bằng cách thực hiện giao cắt đường-AABB . Những điểm này được đánh dấu bằng các vòng tròn màu xanh.
Trong hình sau đây, một nguồn gốc khác nhau đã được sử dụng và các điểm giao nhau giống nhau được tìm thấy.
Nhiều AABB di chuyển
Để làm cho công việc này cho hai AABB di chuyển theo kiểu tuyến tính trong một khoảng thời gian cụ thể, bạn sẽ trừ vectơ vận tốc của B khỏi vectơ vận tốc của A và sử dụng nó làm đoạn thẳng cho giao điểm AABB.
Mã giả
def normalize(aabb):
return {x1: min(aabb.x1, aabb.x2), x2: max(aabb.x1, aabb.x2),
y1: min(aabb.y1, aabb.y2), y2: max(aabb.y1, aabb.y2),
def rotate_about_origin(aabb):
return normalize({x1: -aabb.x1, x2: -aabb.x2
y1: -aabb.y1, y2: -aabb.y2})
# given normalized aabb's
def minkowski_sum(aabb1, aabb2):
return {x1: aabb1.x1+aabb2.x1, x2: aabb1.x2+aabb2.x2,
y1: aabb1.y1+aabb2.y1, y2: aabb1.y2+aabb2.y2}
def get_line_segment_from_origin(v):
return {x1: 0, y1: 0, x2: v.x, y2: v.y}
def moving_objects_with_aabb_intersection(object1, object2):
A = object1.get_aabb()
B = object2.get_aabb()
# get A'⊕B
rotated_A = rotate_about_origin(A)
sum_aabb = minkowski_sum(rotated_A, B)
# get v'
total_relative_velocity = vector_subtract(object1.get_relative_velocity(), object2.get_relative_velocity())
line_segment = get_line_segment_from_origin(total_relative_velocity)
# call your favorite line clipping algorithm
return line_aabb_intersection(line_segment, sum_aabb)
Phản ứng va chạm
Tùy thuộc vào lối chơi, bạn sẽ thực hiện phát hiện va chạm chi tiết hơn (có thể là AABB có chứa các mắt lưới) hoặc chuyển sang giai đoạn tiếp theo: phản ứng va chạm.
Khi có xung đột, thuật toán giao tuyến AABB sẽ trả về 1 hoặc 2 điểm giao nhau tùy thuộc vào việc A kết thúc chuyển động của nó bên trong B hay đi qua nó, tương ứng. (Đây là chiết khấu cho các trường hợp thoái hóa trong đó A gặm cỏ B dọc theo hai bên hoặc dọc theo một trong các góc tương ứng của chúng.)
Dù bằng cách nào, điểm giao nhau đầu tiên dọc theo đoạn đường là điểm va chạm, bạn dịch nó trở lại vị trí chính xác trong hệ tọa độ thế giới (vòng tròn màu xanh nhạt đầu tiên trong hình thứ hai dọc theo v gốc , gọi nó là p ) và sau đó quyết định (ví dụ: đối với va chạm đàn hồi bằng cách phản xạ v dọc theo va chạm bình thường tại p ) vị trí thực tế của A ở cuối khung sẽ là ( At + 1 ).
Nếu có nhiều hơn chỉ 2 máy va chạm thì điều này sẽ phức tạp hơn một chút, vì bạn muốn thực hiện phát hiện va chạm cho lần thứ hai, được phản ánh, một phần của v .