วิธีจัดการกับการชนมุมในแบบ 2D อย่างไร


22

ฉันกำลังเขียนเกม XNA ระดับบนลงล่าง ตั้งแต่ครั้งแรกที่ฉันพยายามเขียนฟิสิกส์และชนสิ่งต่าง ๆ เพื่อเรียนรู้

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

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

การชนมุม

ขณะนี้รหัสของฉันบอกฉันว่าขอบกำแพงทั้งสองได้ถูกตัดกัน แต่ไม่ใช่ขอบใดที่มันจะชนกันก่อนดังนั้นจึงควรจะตัดขอบไหน

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



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

คำตอบ:


9

ถ้าคุณคำนวณวิธีไกลเข้าไปในได้ย้ายคุณสามารถอาจฐานบนสามเหลี่ยมของ x และ y พิกัดของมุมที่ตัด ฉันหวังว่าจะมีเหตุผลฉันไม่สามารถนึกถึงวิธีที่ดีกว่าที่จะพูดWallPlayer Sprite

ตัวอย่างเช่นถ้าคุณดูไดอะแกรมของคุณ ใช้xค่าของมุมซ้ายด้านบนของPlayer Sprite(หลังจากย้าย) และลบค่าของมุมขวาด้านล่างของx Wallทำสิ่งเดียวกันสำหรับyค่าแล้วดูว่าอันไหนใหญ่กว่า ที่สำคัญคือถ้ามีขนาดใหญ่กว่าอีกคนหนึ่งPlayer Spriteอาจจะตัดกันในด้านนั้น

นี่คือตัวอย่างรูปภาพ (นี่เป็นส่วนย่อยของภาพของคุณที่เพิ่มบรรทัดของตัวเอง):

ตัวอย่างทางแยก

ทีนี้คุณเห็นตรงนี้ว่าเส้นสีน้ำเงินใหญ่กว่าเส้นสีเขียว ในกรณีนี้เส้นสีน้ำเงินจะอยู่ข้างๆที่Player Spriteคาดว่าจะเด้งออกมา

หากค่าทั้งสองเท่ากันค่าจะชนกันที่มุม

ตอนนี้มีปัญหาเล็กน้อยในการทำเช่นนี้ หากการPlayer Spriteเดินทางนั้นเร็วมากหรือการชนกันอยู่ใกล้กับมุมมากอาจเป็นไปได้ว่าการเคลื่อนที่นั้นPlayer SpriteอาจจะไปWallในทิศทางที่ผิด ในกรณีนี้คุณอาจต้องตรวจสอบความเร็วของวัตถุที่เคลื่อนที่ (ดูคำตอบของ Nathan Reed )

หมายเหตุ: ฉันคิดว่าฉันกำลังพยายามอธิบายการตรวจจับการชน SAT ที่ @Blau พูดถึง แต่ฉันใช้เวลานานในการเขียนสิ่งนี้ดังนั้นฉันจะโพสต์ต่อไป หวังว่ามันจะช่วยคุณได้บ้าง


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

@TerryB - การหมุนเพิ่มความซับซ้อนอีกเล็กน้อย คุณอาจต้องการอ่านค่าในกล่องขอบที่มีการจัดแนวแกน (AABB) โดยพื้นฐานแล้วคุณยังคงใช้หลักการเดียวกันกับข้างต้นโดยการทดสอบกล่องขนาดเล็กที่สุดที่วัตถุที่หมุนได้จะพอดี แต่แกนที่อยู่ในแนวเดียวกันกับแกนคาร์ทีเซียน ลองนึกภาพถ้าคุณมีสี่เหลี่ยมจัตุรัสและคุณหมุนไป 45 องศาเพื่อทำให้มันเป็นเพชร การคำนวณการชนกันของสิ่งนั้นจะยากและมีค่าใช้จ่ายดังนั้นก่อนอื่นให้ตรวจสอบว่าวัตถุนั้นอยู่ใกล้กับวัตถุหรือไม่โดยใช้ AABB ซึ่งจะเป็นรูปสี่เหลี่ยมจัตุรัสซึ่งแต่ละจุดของเพชรสัมผัสกับแต่ละด้านที่อยู่ตรงกลาง
Richard Marskell - Drackir

จากนั้นเมื่อคุณรู้ว่ามันอยู่ใกล้คุณสามารถทำการคำนวณราคาแพงกว่าเพื่อดูว่าพวกมันตัดกับมุมหรือไม่ (ซึ่งน่าจะเป็นคำถามอีกข้อ :)
Richard Marskell - Drackir

1
-1 เนื่องจากการกระจัดต่ำสุดไม่ได้ให้คำตอบที่ถูกต้องกับ "ขอบใดที่ชนกันก่อน"; เห็นคำตอบของฉัน
นาธานรีด

@NathanReed - ซึ่งเป็นเหตุผลที่ฉันกล่าวถึงการตรวจสอบความเร็วใน "ตอนนี้มีปัญหาเล็กน้อยกับการทำแบบนี้" วรรค
Richard Marskell - Drackir

15

การกระจัดต่ำสุดนั้นไม่ได้ให้คำตอบที่ถูกต้องสำหรับการชนขอบก่อนเสมอ พิจารณากรณีนี้:

กรณีที่แบ่งอัลกอริทึมการกระจัดสั้นที่สุด

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

timeXCollision = (player.left - wall.right) / -player.velocity.x
timeYCollision = (wall.bottom - player.top) / player.velocity.y

(นี่เป็นการสมมติว่าระบบพิกัด X-right, Y-up) โดยทั่วไปคุณจะต้องใช้สัญลักษณ์ของส่วนประกอบ X และ Y ของผู้เล่นความเร็วในการกำหนดว่าต้องทำการทดสอบคู่ของขอบใด อย่างไรก็ตามเมื่อคุณมีการคำนวณการชนครั้งก่อนหน้าของทั้งสองคือการชนที่คุณต้องจัดการ


1
คุณสามารถยกตัวอย่างเกี่ยวกับวิธีการปรับใช้ตัวแปรสองตัวของคุณได้อย่างไร
BjarkeCK

1

คุณต้องมีการตรวจสอบการชนของ SAT

โดยทั่วไปคุณต้องค้นหาเวกเตอร์การกระจัดต่ำสุดที่ substracted กับวัตถุอย่างใดอย่างหนึ่งปล่อยให้พวกเขาไม่ตัดกัน

ในภาพของคุณการกระจัดต่ำสุดคือส่วนสีส้ม

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


4
-1 เนื่องจากการกระจัดต่ำสุดไม่ได้ให้คำตอบที่ถูกต้องกับ "ขอบใดที่ชนกันก่อน"; เห็นคำตอบของฉัน
นาธานรีด

ใครถามว่า
Blau

คำถามคือถามว่า "รหัสของฉันบอกฉันว่าขอบกำแพงทั้งสองได้ถูกตัดกัน แต่ไม่ใช่ขอบใดที่มันจะชนก่อนแล้วจึงจะตีกลับที่ไหน
นาธานรีด

ครั้งแรก? ปัญหาไม่ใช่สิ่งแรกคือมันชนกับขอบทั้งสองในเวลาเดียวกัน ... เรื่องที่ว่าขอบไหนที่จะกระเด็นคุณเลือกวิธีหนึ่งที่ดีสำหรับคุณฉันได้เลือกวิธีที่เป็น ดีสำหรับฉันทั้งคู่ใช้ได้
Blau

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

0

ตอบคำถามที่คล้ายกันที่นี่

คุณอาจต้องการพิจารณาการตรวจสอบตำแหน่งก่อนหน้า -

ตัวอย่างเช่นหากก่อนหน้านี้ด้านซ้ายของคุณอยู่ทางด้านขวาของด้านขวาของพวกเขาและคุณเกิดการชนการชนทางขวานั้นเกิดขึ้น

หากคุณทำเช่นนี้เพียงแก้ไขการชนแกน y ตรวจสอบว่าคุณชนอะไรหรือไม่จากนั้นแก้ไขการชนแกน x

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