อัลกอริธึมการชนกันของสี่เหลี่ยมผืนผ้าแบบสองมิติอย่างง่าย ๆ ที่กำหนดว่าด้านใดที่สี่เหลี่ยมนั้นชนกัน


16

เริ่มแรกฉันลองใช้การตัดกันเป็นรูปสี่เหลี่ยมผืนผ้าซึ่งทำงานได้ดี อย่างไรก็ตามเมื่อฉันต้องใช้ระบบฟิสิกส์เช่นความเร็วความเร่งและเวกเตอร์ทิศทางฉันจะต้องหาวิธีที่จะกำหนดว่าด้านใดของสี่เหลี่ยมที่ชนกัน ตอนนี้ในระบบของฉันไม่มีสี่เหลี่ยมหมุนดังนั้นนี่ทำให้ปัญหาง่ายขึ้น อย่างไรก็ตามฉันไม่สามารถหาวิธีที่ง่ายในการพิจารณาว่าสี่เหลี่ยมด้านใดที่ชนกัน ฉันเคยจัดการกับปัญหานี้มาก่อน แต่ล้มเหลวอย่างน่าสังเวช

สิ่งที่ฉันทำในอดีตคือการกำหนดระยะห่างระหว่างแต่ละด้านของสี่เหลี่ยมมุมฉากและตรวจสอบว่าระยะทางใกล้กับ 0 (ใช้บางช่วงระยะแรกที่กำหนดไว้) หรือเป็น 0 อย่างไรก็ตามสำหรับเลขคณิตจุดลอยตัวนี้พิสูจน์ได้ว่าไม่เสถียรเพราะ ของการล่วงเลยเวลาที่ไม่รู้จัก บางครั้งสี่เหลี่ยมจริง ๆ แล้วจะตัดกันก่อนที่จะตรงกับช่วงที่กำหนด

ในทางกลับกันฉันกำลังคิดที่จะวางไข่หลายรูปสี่เหลี่ยมแต่ละสี่เหลี่ยมสำหรับแต่ละด้าน อย่างไรก็ตามหลังจากคิดอีกครั้งมันจะเหมือนกับการมีด้านขนานกับการตรวจสอบช่วงระยะทางเพียงแค่ว่าช่วงระยะทางนั้นคือความกว้างของสี่เหลี่ยมเล็ก ๆ แต่ละอัน

ดังนั้นข้อเสนอแนะสำหรับปัญหานี้หรือไม่?


คุณใช้การอัปเดตตำแหน่งแบบไม่ต่อเนื่องหรือต่อเนื่องหรือไม่ (คุณกำลังปรับปรุงความเร็วของคุณโดยการเร่งความเร็วทุกเฟรมแล้วคำนวณตำแหน่งหรือใช้ฟังก์ชั่นเพื่อประเมินตำแหน่ง)
Casey Kuball

คำตอบ:


24

ดัดแปลงมาจากคำตอบของฉันไปที่"โดนด้านใด?" :

ผมขอแนะนำให้คำนวณผลรวมคอฟสกีของ B และ A ซึ่งเป็นรูปสี่เหลี่ยมผืนผ้าใหม่และการตรวจสอบที่เป็นศูนย์กลางของการโกหกสี่เหลี่ยมค่อนข้างที่สี่เหลี่ยมผืนผ้าใหม่ (ที่จะรู้ว่าไม่ว่าจะเป็นความขัดแย้งที่เกิดขึ้น) และเส้นทแยงมุมของมัน (จะรู้ว่าที่การปะทะกัน กำลังเกิดขึ้น):

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
ฉันต้องการเพิ่มว่า 'ด้านบน' และ 'ด้านล่าง' สัมพันธ์กับระบบพิกัดของคุณ ตัวอย่างเช่นในเกมของฉัน (0,0) อยู่ที่มุมบนซ้ายดังนั้นพวกมันจึงกลับด้านจากตัวอย่างของคุณ สิ่งที่ต้องจำไว้
Neikos

ทางออกที่ดีทำงานได้ดีมากสำหรับความต้องการของฉัน
Opiatefuchs

1
มีความผิดพลาดบางอย่างกับ dx กลายเป็น 0 หรือ dy กลายเป็น 0 หรือทั้งสองอย่าง? ขอผมใช้เหตุผลหน่อย ... ถ้า dx = 0 && dy == 0 นั่นหมายความว่าทั้งสองรูปสี่เหลี่ยมมีจุดกำเนิดเดียวกันจากนั้นอัลกอริทึมจะส่งกลับด้านล่างเป็นค่าเริ่มต้นหรือไม่ หากหนึ่งในนั้นคือ 0 ดังนั้นคาดว่าผลลัพธ์ที่ถูกต้อง ดังนั้นฉันคิดว่าอัลกอริทึมนี้ถูกต้องยกเว้นกรณีที่ dx == 0 && dy == 0 ซึ่งควรไม่ได้กำหนดและไม่อยู่ด้านล่าง ดังนั้นระวัง & ขอบคุณ
Prasanth

1
ตอนนี้ฉันกำลังสงสัยว่าเกิดอะไรขึ้นเมื่อ dx == dy, w == h ... จากนั้นรหัสก็ตัดสินว่าผลลัพธ์นั้นเป็นด้านหนึ่งเมื่อมันไม่ได้กำหนดจริง ๆ แล้ว .. จินตนาการถึงสองกำลังสองที่ตัดกันจนศูนย์กลางของจตุรัสอยู่ที่ อีกมุมหนึ่งของสี่เหลี่ยมจัตุรัสและอีกมุมหนึ่งของจัตุรัสอยู่ที่มุมหนึ่งของสี่เหลี่ยมจัตุรัส ที่นี่ด้านควรจะไม่แน่นอน - มันไม่ถูกหรือด้านล่าง มันทั้งคู่!
Prasanth
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.