การตอบสนองการปะทะกันของเกม 2D: SAT และการเคลื่อนที่ขั้นต่ำตามแกนที่กำหนดหรือไม่


13

ฉันพยายามนำระบบการชนมาใช้ในเกม 2D ที่ฉันทำ ทฤษฎีแกนการแยก (ตามที่อธิบายโดยบทช่วยสอนการชนของ metanet ) ดูเหมือนจะเป็นวิธีที่มีประสิทธิภาพและมีประสิทธิภาพในการจัดการการตรวจจับการชน แต่ฉันไม่ชอบวิธีการตอบสนองการชนที่พวกเขาใช้ ด้วยการแทนที่แกนอย่างเหลื่อมซ้อนกันอย่างสุ่ม ๆ อัลกอริธึมก็เพิกเฉยตำแหน่งก่อนหน้าของวัตถุที่เคลื่อนที่ซึ่งหมายความว่ามันจะไม่ชนกับวัตถุเคลื่อนที่มากเท่าที่มันเข้ามาแล้วก็เด้งออกมา

นี่คือตัวอย่างของสถานการณ์ที่สำคัญ:

ตัวอย่าง

ตามวิธี SAT อธิบายข้างต้นสี่เหลี่ยมจะโผล่ออกมาจากสามเหลี่ยมตั้งฉากกับด้านตรงข้ามมุมฉากของมัน:

SAT-Style Response

อย่างไรก็ตามตามความเป็นจริงสี่เหลี่ยมควรหยุดที่มุมล่างขวาของรูปสามเหลี่ยมซึ่งจะเป็นจุดที่เกิดการชนครั้งแรกถ้ามันเคลื่อนไหวอย่างต่อเนื่องตามเวกเตอร์การกระจัด:

การตอบสนองที่สมจริง

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

(ข้ามโพสต์จาก StackOverflow หวังว่าจะไม่ผิดกฎ!)


มันผิดกฎ อย่าขวางทาง
AttackHobo

ใช่ลบออกจาก StackOverflow และเก็บไว้ที่นี่: P
TravisG

gamedev.stackexchange.com/questions/9144/…ฉันตอบคำถามเฉพาะของคุณที่นี่
ultifinitus

ลบจาก SO
Archagon

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

คำตอบ:


11

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

ในภาพประกอบด้านล่างวัตถุสีน้ำเงินกำลังเคลื่อนที่และวัตถุสีแดงนิ่ง 1 ขั้นตอนที่ 1:สำหรับแต่ละรูปหลายเหลี่ยมให้หาจุดที่ไกลที่สุดสองจุดไปตามเส้นโครงของรูปหลายเหลี่ยมนั้นลงบนเส้นตั้งฉากกับเวกเตอร์เคลื่อนที่ 2 ขั้นตอนที่ 2:แบ่งแต่ละรูปหลายเหลี่ยมตามเส้นเชื่อมต่อจุดเหล่านี้ ครึ่งหนึ่งของรูปหลายเหลี่ยมที่หันหน้าไปทางรูปหลายเหลี่ยมอื่น ๆ ตามการเคลื่อนที่ของเวกเตอร์คือ "ตัวเรือเดินหน้า" นี่เป็นเพียงส่วนเดียวของรูปหลายเหลี่ยมที่อาจชนกันได้ 3 ขั้นตอนที่ 3:ฉายเวกเตอร์จากแต่ละจุดใน "ฮัลล์ไปข้างหน้า" ของรูปหลายเหลี่ยมตามเวกเตอร์ที่เคลื่อนไหวไปยังรูปหลายเหลี่ยมที่ตรงกันข้ามและตรวจสอบการตัดกันกับขอบของ "ฮัลล์ไปข้างหน้า" ของรูปหลายเหลี่ยมที่ตรงกันข้าม (อาจช้า แต่คอมพิวเตอร์ค่อนข้างเร็วทุกวันนี้ใช่ไหม?) (ขออภัยเกี่ยวกับลูกศรเอียงลูกศรทั้งหมดควรขนานกัน) 4 ขั้นตอนที่ 4:ใช้เวกเตอร์ที่สั้นที่สุด นี่คือระยะการชนที่แน่นอน 5 ขั้นตอนที่ 5: Voila! 6


2
มันค่อนข้างน่าประทับใจ คุณเคยเปรียบเทียบความเร็วของอัลกอริทึมของคุณกับการสุ่มอย่างง่าย (4x หรือ 8x) หรือไม่?
TravisG

น่าเสียดายที่ไม่มี
Archagon

น่าประทับใจและฉันแน่ใจว่าคณิตศาสตร์ไม่ซับซ้อนเกินไป +1
you786

7

ลองดูคำถามที่คล้ายกันนี้: การ แก้ปัญหาการชนกัน

และจากhttp://www.metanetsoftware.com/technique/tutorialA.html#section5 (ซึ่งคุณโพสต์ลิงก์ไปยัง :))

ส่วนที่ 5: วัตถุที่เคลื่อนไหวเร็ว

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

หากคุณต้องมีอย่างแน่นอนมีวิธีการทั่วไปสองวิธีในการจัดการกับวัตถุขนาดเล็กและ / หรือเคลื่อนไหวเร็ว: การทดสอบการชนแบบกวาดและการสุ่มหลายตัวอย่าง

- = การทดสอบการกวาด = -

แทนที่จะทำการทดสอบการแยกระหว่างรูปร่างคงที่สองเราสามารถสร้างรูปร่างใหม่โดยกวาดรูปร่างดั้งเดิมไปตามวิถีและทดสอบการทับซ้อนระหว่างรูปร่างกวาดเหล่านี้

แนวคิดพื้นฐานอธิบายไว้ใน [Gomez] สำหรับการทดสอบแบบวงกลมและ AABB-AABB

- = multisampling = -

ทางเลือกที่ง่ายกว่ามากสำหรับการทดสอบแบบ swept คือการมัลติตัวอย่าง; แทนที่จะทำการทดสอบแบบสแตติกเดี่ยวที่ตำแหน่งใหม่ของวัตถุดำเนินการทดสอบหลายอย่างที่หลายตำแหน่งที่อยู่ระหว่างตำแหน่งก่อนหน้าและตำแหน่งใหม่ของวัตถุ เทคนิคนี้ใช้เพื่อชน ragdoll ใน N

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

แก้ไข

โดยสรุปและ AFAIK มีวิธีแก้ปัญหาไม่กี่อย่าง

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

1

ขึ้นอยู่กับว่าคุณต้องการแค่การเคลื่อนที่เชิงเส้นหรือถ้าคุณต้องการรับมือกับการเคลื่อนไหวเชิงมุมเช่นกัน

ทางเลือกอื่นในการใช้ SAT:

ในกรณีที่เป็นแบบเส้นตรงเท่านั้นที่คุณสามารถนำไปทิ้งไว้กับ Minkowski ความแตกต่างของรูปหลายเหลี่ยมสองรูปจากจุดกำเนิดในทิศทางของความเร็วเชิงเส้นเดลต้าของวัตถุ

ถ้ารังสีกระทบกับ MD วัตถุทั้งสองจะชนกันและจุดที่จะบอกเวลาที่พวกมันชนกัน

ทีนี้ถ้าวัตถุเคลื่อนไหวและหมุนมันจะยากขึ้น แต่คุณก็ยังสามารถใช้เทคนิคที่คล้ายกันได้ อนุรักษ์นิยมก้าวหน้าจะช่วยให้คุณสามารถจัดการกับกรณีนี้ เทคนิคนี้ซ้ำแล้วซ้ำอีก; การวนซ้ำแต่ละครั้งจะสร้าง MD ใหม่และนำคุณเข้าใกล้เวลาของการตัดกัน

นี่คือกระดาษร่างต้นฉบับเกี่ยวกับความก้าวหน้าอนุรักษ์นิยม:

http://www.continuousphysics.com/BulletContinuousCollisionDetection.pdf

ฉันเขียนบทความเพื่ออธิบายเทคนิคในรายละเอียดบางอย่างที่นี่:

http://www.wildbunny.co.uk/blog/2011/04/20/collision-detection-for-dummies/

หวังว่าความช่วยเหลือเหล่านี้!

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