การแก้ไขการชนกับกองกำลัง


14

ในเอนจินฟิสิกส์ 2D ของฉันฉันสามารถตรวจจับการชน AABB กับ AABB และแก้ไขพวกมันได้โดยการหาเวกเตอร์การสอดใส่ที่สั้นที่สุดและเพิ่มลงในตำแหน่งของ AABB

การทำเช่นนี้จะ "ผลัก" AABB ตัวแรกนอก AABB ตัวที่สอง แต่ไม่ได้เกี่ยวข้องกับการเปลี่ยนแปลงความเร็ว / การเร่งความเร็วเลย

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

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

ฉันอ่านออนไลน์ที่แก้ไขการชนโดยการทำงานกับตำแหน่งด้วยตนเองหรือความเร็วไม่ถูกต้อง ฉันพยายามใช้กองกำลัง (มวลคือ "hardcoded" 1 สำหรับตอนนี้):

void Body::applyForce(sf::Vector2f mForce) { acceleration += mForce; }

void Body::integrate(float mFrameTime)
{
    velocity += acceleration * mFrameTime;
    position += velocity * mFrameTime;

    acceleration = {0, 0};
}

ถ้าฉันใช้เวกเตอร์การสอดใส่ที่สั้นที่สุดเป็นแรงในระหว่างการแก้ไขการชน AABB แบบไดนามิกจะได้รับ "ผลักออก" จากแบบคงที่ แต่ความเร็วของมันจะไม่ลดลงในแบบจำลองที่ไม่มีแรงโน้มถ่วงและมันจะเคลื่อนที่ตลอดไป

มีวิธีการใช้กำลัง "ชั่วคราว" หรือไม่? แรงที่เกี่ยวข้องกับการผลัก AABB แรกออกจาก AABB ที่สองจากนั้นจะหยุดเมื่อ AABB ไม่ชนกันอีกต่อไป?

มีซอร์สโค้ดทั้งหมดที่นี่: https://github.com/SuperV1234/SSVSCollision


1
ฉันสนใจสิ่งนี้ คุณมีวิธีแก้ปัญหาหรือยัง?
TravisG

@TravisG: ยังไม่น่าเสียดาย พรุ่งนี้ฉันจะเพิ่มเงินรางวัลถ้าฉันไม่ได้รับคำตอบใด ๆ
Vittorio Romeo

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

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

@dreta สมมติฐานของเขาดี เขาชี้ให้เห็นว่ามวลของเขาสำหรับวัตถุทั้งหมดเป็นเพียง "1" ในตอนนี้ซึ่งทำให้ส่วนรหัสของเขาใช้ได้ ถึงแม้ว่า Box2D อาจจัดการกับความเร็วโดยตรง แต่ก็ต้องจัดการกับปัญหาเดียวกัน หากแทนที่จะใช้กำลัง Box2D จะใช้แรงกระตุ้น แต่อย่างใดก็ยังต้องจัดการกับความจริงที่ว่าแรงกระตุ้นนั้นไม่ได้หายไปเมื่อแยกวัตถุ แม้ว่าเป็นไปได้ว่าในความเป็นจริงมันไม่ได้เกี่ยวข้องกับเรื่องนี้เลยและปล่อยให้วัตถุเก็บพลังงานของพวกเขา (มันจะเป็นเช่นนี้ในโลกแห่งความเป็นจริงหลังจากทั้งหมด)
TravisG

คำตอบ:


13

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


สำหรับวิธีที่รวดเร็วในการสร้างแบบจำลองความละเอียดการชนที่แม่นยำยิ่งขึ้นของวัตถุสองรายการ A และ B:

  1. ค้นหาตำแหน่งที่ถูกต้องก่อนการชน คุณใกล้เคียงกับสิ่งนี้โดย: "ค้นหาเวกเตอร์การสอดใส่ที่สั้นที่สุดและเพิ่มลงในตำแหน่งของ AABB"
  2. ค้นหาความเร็วหลังจากการชนโดยใช้ฟิสิกส์ของนิวตัน :
    • สำหรับกรณีที่มวลถูกเขียนโค้ดแบบแข็งเป็น 1 เพียงแค่เปลี่ยนความเร็ว (สิ่งนี้ไม่ได้ใช้กับวัตถุคงที่ซึ่งต้องมีมวลไม่สิ้นสุด)
      • Av = Bu
      • Bv = Au
    • หากวัตถุ A และ B มีมวลต่างกัน:
      • Av = (Au * (Am - Bm) + (2 * Bm * Bu)) / (Am + Bm)
      • Bv = (Bu * (Bm - Am) + (2 * Am * Au)) / (Am + Bm)
    • ที่อยู่:
      • v: ความเร็วหลังการชน
      • u: ความเร็วก่อนการชน
      • m: มวล (ใช้จำนวนที่มากที่สุดเท่าที่เป็นไปได้สำหรับมวลของวัตถุคงที่)
  3. ตั้งค่าความเร่งเป็น 0:ความเร่งจากการชนถูกคำนวณโดยการคำนวณความเร็วในขั้นตอนที่ 2

โปรดดูที่โปรแกรมดาวเคราะห์น้อยตัวอย่างของฉันซึ่งแสดงให้เห็นถึงแนวคิดเหล่านี้


ถัดไปบัญชีสำหรับวัตถุที่ซ้อนกัน:

ดังที่คุณได้กล่าวไว้การใช้ความเร็วในการจำลองวัตถุที่วางซ้อนกัน / พักผ่อนไม่ได้ผล: ความเร็วคือความเร็วที่วัตถุเคลื่อนที่ดังนั้นหากมันวางอยู่บนวัตถุคงที่ความเร็วควรอยู่ใกล้ 0 มันไม่สมเหตุสมผลที่จะเพิ่มขึ้น ความเร็วของวัตถุที่จะทำให้มันปรากฏที่เหลือ:

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

สิ่งที่ควรเกิดขึ้นจริง ๆ คือแรงเร่งที่เกิดขึ้นในทิศทางตรงกันข้ามเนื่องจากแรงโน้มถ่วงควรยกเลิกแรงโน้มถ่วง (ซึ่งเรียกว่าแรงปะทะปกติ) ทางลัดคือการไม่ใช้แรงโน้มถ่วงกับร่างกายที่ไม่ได้อยู่ในอากาศ:

  • วิธีการหนึ่งในการทำสิ่งนี้โดยรักษาสถานะ "มีเหตุผล":
    • อย่าใช้แรงโน้มถ่วงกับวัตถุในสภาวะที่มีสายดิน
    • หากวัตถุชนกับวัตถุจากด้านล่างและความเร็วของวัตถุนั้นเล็กมากมันจะเข้าสู่สถานะที่มีการลงดิน
    • วัตถุออกจากสถานะกราวด์เมื่อความเร็วแนวดิ่งเกินค่าบวกที่แน่นอน

ปรับปรุง:

  • ในแง่ของคนธรรมดาฟิสิกส์ของนิวตันบอกว่าพลังงานทั้งหมดก่อนและหลังการชนจะต้องตรงกัน เมื่อวัตถุสองชิ้นชนกันพลังงานของพวกมันจะถูกกระจายใหม่ พลังงานคือการรวมกันของความเร็วและน้ำหนัก: สิ่งที่หนักกว่าและเร็วกว่ามีพลังงานมากกว่า นั่นง่าย อย่างไรก็ตามสิ่งที่ไม่ง่ายคือน้ำหนักที่แน่นอนส่งผลต่อการกระจายพลังงาน
  • การเปลี่ยนความเร็วเป็นทางลัดสำหรับวัตถุที่ไม่มีการผสมสองแบบไดนามิกที่มีมวลเท่ากัน (วัตถุคงที่และคงที่มีขนาดใหญ่มากและไม่มีที่สิ้นสุด)
  • ช็อตคัตเมื่อตัวแบบคงที่อันใดอันหนึ่งได้รับการแก้ไขคือ: ตัวแบบไดนามิกตัวอื่นที่ยังคงความเร็วจะคงที่ มีการเปลี่ยนมุมเท่านั้น (ลองนึกภาพโต๊ะพูลเมื่อลูกบอลกระทบกับรางรถไฟโดยพื้นฐานแล้วจะมีขนาดใหญ่มากและไม่มีที่สิ้นสุด)
  • สำหรับกรณีอื่น ๆ เช่นวัตถุสามชิ้นขึ้นไปสมการการเคลื่อนที่ของนิวตันจะต้องได้รับการแก้ไข (การอนุรักษ์โมเมนตัมและการอนุรักษ์พลังงานจลน์)
  • ฉันไม่แน่ใจว่าสมการของนิวตันสำหรับการเคลื่อนที่สามารถแก้ไขได้มากกว่าสองร่าง อย่างไรก็ตามโชคดีที่วัตถุสามชิ้นแทบไม่เคยชนกันในเวลาเดียวกัน มันเพียงพอที่จะจัดการกับสองศพแรกที่ชนกันจากนั้นจัดการกับการชนใด ๆ ต่อไปนี้โดยใช้ความเร็วใหม่จากการแก้ปัญหาการชนก่อนหน้านี้ นี่เป็นเหตุผลที่ดีที่จะทำให้เวลาฟิสิกส์ของคุณเล็กที่สุดเท่าที่จะเป็นไปได้
  • คุณจะสังเกตเห็นในการสาธิตดาวเคราะห์น้อยของฉันว่ามีวัตถุมากมายถูกสร้างขึ้นเนื่องจากหินที่ใหญ่กว่าถูกแบ่งออกเป็นก้อนเล็ก ๆ อย่างไรก็ตามฉันมักจะจัดการการชนกันระหว่างคู่ของร่างกาย; ไม่เคยจัดการการชนที่มีมากกว่าสองร่างอย่างชัดเจน

ขอบคุณสำหรับการตอบกลับอย่างละเอียด มีบางอย่างที่ฉันไม่เข้าใจ: การสลับความเร็วทำงานได้ดีในการชนกับ 2 ศพ - แต่ฉันไม่เห็นว่ามันจะทำงานได้อย่างไรเมื่อมีวัตถุหลายชิ้น (และร่างคงที่) ชนกันทั้งหมดในเวลาเดียวกัน แม้ไม่มีแรงโน้มถ่วงการมีร่างกายแบบไดนามิกชนกันในเวลาเดียวกันกับร่างกายแบบคงที่และร่างกายแบบไดนามิกอื่นทำให้เกิดปัญหา เนื่องจากการสลับความเร็วนั้นขึ้นอยู่กับลำดับของการชน หากร่างกายแบบคงที่ชนกันเป็นครั้งสุดท้ายร่างกายจะหยุดเคลื่อนไหว หากเป็นแบบไดนามิกร่างกายจะย้ายอีกครั้ง สิ่งนี้ได้รับการแก้ไขอย่างไร
Vittorio Romeo

@Vee: คำถามที่ดี! สามเนื้อหา + และร่างคงเป็นสองประเด็นแยกกัน ฉันพูดถึงทั้งคู่ในการอัพเดท สรุป: จัดการการชนกันของวัตถุสองวัตถุในเวลาเดียวกัน วัตถุที่เคลื่อนที่ได้มีมวลมากและไม่มีที่สิ้นสุด
Leftium

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

16

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

หากคุณต้องการแก้ไขการทับซ้อนคุณสามารถใช้ความเร็วหลอกเทียมที่สร้างวิถีการแยกโดยไม่เพิ่มโมเมนตัม สิ่งนี้ทำได้ในตัวแก้ตำแหน่งของ Box2D

ฉันแนะนำให้รับงานนำเสนอ GDC ของฉันตั้งแต่ปี 2549 และ 2550 ที่นี่:

http://code.google.com/p/box2d/downloads/list

นอกจากนี้คุณสามารถดู Box2D Lite เพื่อการใช้งานที่ง่ายขึ้น


+1 สำหรับคำพูดของความจำเป็นในการปรับตำแหน่งเช่นกัน มีเพียงไม่กี่คนที่หลงไหลสิ่งนี้ แต่เพื่อเพิ่มความเสถียรในการจำลองเครื่องยนต์ส่วนใหญ่โกงโดยการปรับตำแหน่งโดยตรง สรุปถ้าเป็นไปได้มันใช้ได้กับเกม
Teodron

ขอบคุณสำหรับคำตอบ. ฉันต้องการที่จะรู้ว่ามีอะไรบ้างที่ฉันอาจพลาดในการนำเสนอ: มีการจัดการวัตถุแบบคงที่ใน Box2D เป็นพิเศษหรือไม่? ฉันหมายถึง - จะเกิดอะไรขึ้นถ้าร่างกายที่มีพลังกระทบกับวัตถุที่เคลื่อนที่ได้?
Vittorio Romeo

2

ป้อนคำอธิบายรูปภาพที่นี่

ในโลกแห่งความเป็นจริงไม่มีแรงที่ "ผลัก" ร่างกายหนึ่งนอกร่างกายอีกเพราะวัตถุไม่เคยทะลุกัน สิ่งที่ใกล้เคียงที่สุดคือแรงปกติ : สร้างขึ้นในขณะที่มีการปะทะกันในโลกแห่งความเป็นจริงมันจะป้องกันการรุกในสถานที่แรก

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

ในขณะที่มีความเป็นไปได้ที่จะสร้างแบบจำลองของแรงปกติอย่างชัดเจนมันง่ายกว่าที่จะสร้างแบบจำลองเอฟเฟกต์:

  1. ป้องกันการแยกวัตถุด้วย:
    • การปรับความเร็วด้วยการแก้ไขการชนในขณะที่กระทบ (ดีที่สุด)
    • ปรับตำแหน่งของร่างกายด้วยตนเองเพื่อไม่ให้ตัดกัน (ง่ายขึ้น) คุณกำลังทำสิ่งนี้อยู่ "โดยการค้นหาเวกเตอร์การเจาะที่สั้นที่สุดและเพิ่มลงในตำแหน่งของ AABB"
  2. อย่าใช้แรงโน้มถ่วงซึ่งจะมีแรงปกติยกเลิกแรงโน้มถ่วง
    • วัตถุที่สัมผัสกับวัตถุอื่นด้านล่างจะขึ้นอยู่กับแรงปกติ ดังนั้นจึงเป็นเรื่องของการติดตามวัตถุเหล่านั้น (อันที่จริงวัตถุใด ๆ ที่มีการสัมผัสควรใช้แรงปกติ แต่ไม่ทั้งหมดนี้จะมีผลกระทบสุทธิที่เกี่ยวข้องกับแรงโน้มถ่วง)
    • หากคุณต้องการเพิ่มวัตถุที่สามารถเลื่อนวัตถุอื่น ๆ ที่เป็นมุมคุณจะต้องเพิ่มแรงเสียดทานและองค์ประกอบ x ของแรงปกติ

ผมอธิบายนี้แตกต่างกันเล็กน้อยในคำตอบอื่น ๆ ของฉันซึ่งเป็นชนเพิ่มเติมเกี่ยวกับทั่วไป

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.