ใช้ผลรวม Minkowski
วิธีที่ดีในการแก้ปัญหานี้คือการพิจารณาจุดตัดระหว่างเส้นการเคลื่อนที่ ( v ) ที่แปลเป็นจุดกำเนิด ( v ' ) และผลรวมของMinkowskiของA ที่หมุนรอบ 180 องศาที่จุดกำเนิด ( A' ) และอุปสรรค (เพียงBในกรณีนี้): A' ⊕ B
ในภาพต่อไปนี้ฉันวางA smack-dab ในจุดเริ่มต้นของระบบพิกัดโดยพลการ ช่วยลดความยุ่งยากนี้การทำความเข้าใจเป็นหมุน 180 องศาส่งผลให้A 'และวีแปลไปจุดเริ่มต้นเท่ากับV'
ผลรวมคอฟสกีเป็นสี่เหลี่ยมสีเขียวและจุดตัดของย้ายและนิ่งBสามารถพบได้โดยการทำเส้น AABB สี่แยก จุดเหล่านี้ถูกทำเครื่องหมายด้วยวงกลมสีน้ำเงิน
ในภาพต่อไปนี้มีการใช้จุดกำเนิดที่แตกต่างกันและพบจุดตัดกันเดียวกัน
AABB ที่กำลังเคลื่อนที่หลายตัว
ในการทำให้งานนี้สำหรับ AABB สองตัวที่เคลื่อนที่แบบเชิงเส้นในช่วงเวลาหนึ่งคุณจะลบเวกเตอร์ความเร็วBของจากเวกเตอร์ความเร็วของAและใช้เป็นส่วนของเส้นตรงสำหรับการตัดกันเส้น AABB
รหัสหลอก
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)
การตอบสนองการชนกัน
ขึ้นอยู่กับเกมที่คุณจะทำการตรวจจับการชนอย่างละเอียดยิ่งขึ้น (อาจเป็นของ AABB ที่มีตาข่าย) หรือก้าวไปข้างหน้าในระยะต่อไป: การตอบสนองการชน
เมื่อมีการชนกันอัลกอริธึม line-AABB-intersection จะคืนค่าจุดตัด 1 หรือ 2 จุดขึ้นอยู่กับว่า A สิ้นสุดการเคลื่อนที่ภายใน B หรือผ่านตามลำดับ (นี่คือการลดกรณีที่เลวลงที่ A ถาโถม B ข้างตัวหรือตามมุมใดมุมหนึ่ง)
ไม่ว่าจะด้วยวิธีใดจุดตัดแรกตามส่วนของเส้นตรงคือจุดชนคุณจะต้องแปลงกลับไปยังตำแหน่งที่ถูกต้องในระบบพิกัดโลก (วงกลมสีฟ้าอ่อนแรกในรูปภาพที่สองตามต้นฉบับvเรียกว่าp ) จากนั้นตัดสินใจ (เช่นสำหรับการชนแบบยืดหยุ่นโดยการสะท้อนvตามการชนปกติที่p ) ตำแหน่งที่แท้จริงของAที่ท้ายเฟรมจะเป็นเท่าใด ( ที่ + 1 )
หากมี colliders มากกว่า 2 ตัวสิ่งนี้จะมีความซับซ้อนเพิ่มขึ้นเล็กน้อยเนื่องจากคุณต้องการตรวจจับการชนกันของวินาที, สะท้อน, ส่วนของvเช่นกัน