29/09/2012 - 23:20
ฉันสร้าง git Repo ที่นี่:
https://github.com/ArthurWulfWhite/Bezier-D Distance/
คุณสามารถดาวน์โหลดไฟล์ต้นฉบับเป็นไฟล์ zip ได้ นอกจากนี้ยังมีตัวอย่างที่คุณสามารถรวบรวมโดยใช้ FlashDevelop หากต้องการใช้การสาธิตให้เปิดโครงการใน Flash Develop และคลิก 'ทดสอบโครงการ' ขณะใช้งานการสาธิตให้คลิก LMB เพื่อสุ่มเส้นโค้ง Bezier ใหม่และวงกลมใหม่
โชคดี!
ลิงก์ซิปมองเห็นยาก - เพียงใช้ Ctrl + F แล้วพิมพ์ zip แหล่งข้อมูลนี้แสดงถึงการค้นหาและการเขียนโปรแกรมสองสามสัปดาห์ฉันหวังว่าคุณจะสนุกกับมัน
หากคุณวางแผนที่จะแบ่ง bezier ซ้ำ ๆ เป็นเซ็กเมนต์และตรวจสอบการชนกับพวกเขาฉันขอแนะนำให้สร้าง 100,100 อาร์เรย์ (ตาราง) และวางแต่ละเซ็กเมนต์ในสี่ช่องที่ใกล้ที่สุดดังนั้นคุณจะต้องตรวจสอบการชนกับ 4 / 10,000 ของ แบ่งแต่ละเฟรม
ฉันคิดว่าคุณจะได้รับประโยชน์จาก box2d ทั้งในฐานะโปรแกรมเมอร์และผู้สร้างเกมเนื่องจากมีอุปสรรค์เล็ก ๆ น้อย ๆ ที่ซ่อนอยู่มากมายในการสร้างกลไกทางฟิสิกส์ที่ 'เรียบง่าย' ที่ทำให้การเคลื่อนไหวดูเหมือนเป็นเรื่องเล็กน้อยและลื่นไหลน้อยลง
คำตอบเก่า: วิธีที่บริสุทธิ์
คุณสามารถดูว่าวงกลมชนกับเส้นโค้ง Bezier หรือไม่โดยตรวจสอบระยะห่างระหว่างระยะห่างระหว่างศูนย์กลางของวงกลมกับจุดที่ใกล้ที่สุดบนเส้นโค้ง
สมการสำหรับระยะทาง (โดยทั่วไป)
อธิบายว่า:
สมการ Bezier:
q(t) = (1-t) * ((1-t) * start.(x,y) + t * control.(x,y)) + t*(t * control.(x,y) + (1 - t) * end.(x,y))
สิ่งนี้สามารถสรุปได้ถึง (ด้วยพีชคณิตบางส่วน) - ฉันจะละเว้น (x, y) สำหรับการอ่านได้ (พวกเขายังคงเป็นคะแนนไม่ใช่หนึ่งหมายเลข)
q(t) = (start -2 * cont + end) t^2 + (-2 * start + 2 * control) + start
ระยะทางจากจุด (x, y) คือ:
sqrt ((q(t).x - point.x)^2 + (q(t).y - point.y)^2)
ในการหาจุดที่ใกล้ที่สุดบน bezier ของลูกบอลคุณจะต้องได้รับและหาจุดทั้งหมดที่อนุพันธ์นั้นมีค่าเท่ากับศูนย์ (ราก) มันเป็นพหุนามของระดับที่สามดังนั้นคุณสามารถใช้สูตรปิดได้ แต่อาจไม่น่าเชื่อถือเนื่องจากความแม่นยำของจุดลอยตัวของคอมพิวเตอร์ที่แสดงถึงเศษส่วนอาจไม่เพียงพอ มันดีกว่าที่จะใช้นิวตันหรืออะไรบางอย่างในธรรมชาติ
อนุพันธ์ที่คุณต้องหาหาคือ:
สมมติว่า: a = start b = การควบคุม c = end d = จุดศูนย์กลาง cirlce
ส่วนที่ยุ่งยากคือการคูณจุดนี้คุณต้องใช้ผลิตภัณฑ์ดอท
ถ้าคุณชอบฉันมีรหัสสำหรับสิ่งนี้และฉันสามารถแบ่งปันได้ที่นี่ในรูปแบบของฟังก์ชั่นที่เพียงแค่ส่งกลับบูลีนหากมีการชนกันหรือไม่และมุมของการปะทะกัน ปัญหาบางอย่างอาจปรากฏขึ้นในการใช้งานเอ็นจิ้นการชนอย่างไร้เดียงสาเช่นลูกบอลที่เคลื่อนที่เร็วอาจติดระหว่างเส้นโค้งสองเส้น
ฉันขอแนะนำให้หลีกเลี่ยงตอนนี้เพียงรวมค่าสัมประสิทธิ์สำหรับแกน x และสำหรับแกน y และเพิ่มขึ้น
ใช้วิธีการที่เชื่อถือได้ใด ๆ ที่คุณอาจเลือกเช่นนิวตันเพื่อค้นหารากตรวจสอบระยะทางจากจุดที่อยู่บน bezier, 0 <= t <= 1 ถึงศูนย์กลางวงกลมและตรวจสอบระยะทางสำหรับปลายทั้งสองของ bezier (เริ่มต้น และสิ้นสุด) ไปยังศูนย์กลางวงกลมไม่ว่าอันไหนที่ใกล้เคียงที่สุดจะบอกคุณว่ามีการชน
หากรัศมีมีขนาดเล็กกว่าระยะทางต่ำสุดจะมีการชนกัน
มุมประมาณหนึ่งระหว่างศูนย์กลางของวงกลมและจุดที่ใกล้ที่สุดใน bezier
ที่ถูกกล่าวว่าหากคุณต้องการทำเกมที่มีการชนกันของข้อมูลอย่างแท้จริงฉันขอแนะนำให้คุณทำซ้ำ bezier
q(t) = (1-t) * ((1-t) * start.(x,y) + t * control.(x,y)) + t*(t * control.(x,y) + (1 - t) * end.(x,y))
แบ่งแต่ละชิ้นที่อยู่ตรงกลางซ้ำจนกระทั่งมันมีขนาดเล็กพอให้บอกว่า 10 พิกเซลหรือน้อยกว่าจากนั้นสร้าง bezier ประมาณจากกล่องและใช้Box2dสำหรับฟิสิกส์เพราะมันเป็นไปได้ที่การเขียนรหัสตรวจจับการชนทั้งหมดนี้จะพิสูจน์ได้ว่ายอดเยี่ยม เวลาที่ไม่เพิ่มประสิทธิภาพการเล่นเกมมากนัก การใช้ Box2d ได้พิสูจน์ตัวเองในโครงการที่นับไม่ถ้วนในอดีต