เทคนิคที่ดีในการทำให้วัตถุเคลื่อนที่ระหว่างจุดไปยังจุดใดในการเคลื่อนไหวโค้งที่ดีคืออะไร?
ตำแหน่งสุดท้ายอาจเคลื่อนไหวเช่นวิถีวิถีของขีปนาวุธกลับบ้าน
เทคนิคที่ดีในการทำให้วัตถุเคลื่อนที่ระหว่างจุดไปยังจุดใดในการเคลื่อนไหวโค้งที่ดีคืออะไร?
ตำแหน่งสุดท้ายอาจเคลื่อนไหวเช่นวิถีวิถีของขีปนาวุธกลับบ้าน
คำตอบ:
สมมติว่าคุณต้องการให้สิ่งนี้เป็นแบบทีละเฟรม (ซึ่งเป้าหมายสามารถเคลื่อนที่ได้) และไม่ใช่เส้นทางที่คำนวณไว้ล่วงหน้านี่เป็นเรื่องง่ายอย่างเหลือเชื่อ:
ทุกเฟรมเปรียบเทียบความเร็ว - เวกเตอร์ของขีปนาวุธกับเวกเตอร์( เป้าหมายตำแหน่ง - ขีปนาวุธตำแหน่ง) ; นั่นคือเวกเตอร์ชี้จากขีปนาวุธไปยังเป้าหมาย ทุกเฟรมถ้าเวกเตอร์สองตัวไม่มีทิศทางเดียวกันให้หมุน veloity-vector ไปทางเวกเตอร์อื่น ๆ เล็กน้อยดังนั้นทุกเฟรมที่มิสไซล์จะเข้าใกล้เป้าหมายมากขึ้น
คุณสามารถกำหนดได้ว่าจะหมุนตามเข็มนาฬิกาหรือทวนเข็มนาฬิกาโดยดูที่เครื่องหมายของกากบาทระหว่างเวกเตอร์สองตัว
[แก้ไข] รหัส XNA-ish (ฉันไม่มี XNA เพื่อทดสอบสิ่งนี้):
//Once a frame:
//Get vector spanning from missile to target
Vector2 vectorToTarget = target.Position - missile.Position;
//Convert to Vector3 to do cross-product
Vector3 vectorToTarget3 = new Vector3(vectorToTarget, 0);
Vector3 missileVelocity3 = new Vector3(missile.Velocity, 0);
//Rotate clockwise/counter-clockwise is determined by sign of cross-product
int crossProductSign = Vector3.Cross(missileVelocity3, vectorToTarget3).Z;
//Positive cross-product means rotate counter-clockwise, negative is clockwise
double rotationAngle = 0;
if(crossProductSign > 0)
rotationAngle = -0.05;
else if(crossProductSign < 0)
rotationAngle = 0.05;
//I'm not sure how to do rotation in XNA, but the internets tell me it's something like this:
missile.velocity = Vector2.Transform(missile.velocity, Matrix.CreateRotationZ(rotationAngle))
โปรดทราบว่าเนื่องจากrotationAngle
มีเพียงสามค่าที่เป็นไปได้ค่าที่เป็นไปได้ทั้งหมดMatrix.CreateRotationZ(rotationAngle)
จึงถูกแคชดังนั้นคุณจึงไม่ต้องเรียกมันว่าทุกเฟรม
มีสองเทคนิคที่เป็นไปได้:
เทคนิคแรกคือทำการจำลองด้วยเฟรม นี่เป็นสิ่งที่ดีถ้าคุณกำลังทำอะไรบางอย่างเหมือนจรวดนำกลับในการเล่นเกมซึ่งไม่จำเป็นต้องยิงเป้าของคุณอย่างแน่นอน
ในกรณีนี้คุณต้องการติดตามตำแหน่งและความเร็วของวัตถุ แต่ละเฟรมจะมองทิศทางไปยังเป้าหมายและทิศทางการเคลื่อนไหวปัจจุบันและปรับความเร็วให้เหมาะสม
หากคุณยึดความเร็วในทันทีขีปนาวุธของคุณจะเข้าเป้าเสมอ แต่ถ้าคุณปรับความเร็วด้วยจำนวนเล็กน้อยในแต่ละเฟรมขีปนาวุธของคุณจะโค้งไปยังเป้าหมาย - และหากมันโค้งช้าพอเป้าหมายก็สามารถหลบได้
เทคนิคที่สองคือการใช้วิธีการพารามิเตอร์ สิ่งนี้มีประโยชน์สำหรับการเคลื่อนไหวสิ่งต่าง ๆ ที่คุณต้องการเข้าถึงกลุ่มเป้าหมายของคุณอย่างแม่นยำและคาดการณ์ได้ ในกรณีนี้คุณมักจะใช้ "เวลา" เป็นพารามิเตอร์ของคุณและใส่ลงในฟังก์ชั่นบางชนิด
ชุดฟังก์ชั่นที่มีประโยชน์อย่างยิ่งคือสมการการเคลื่อนที่ที่คุณเรียนรู้ในวิชาฟิสิกส์ระดับมัธยม โดยการใช้สิ่งเหล่านี้กับทั้งสองแกนคุณสามารถรับวิถีกระสุน ด้วยคณิตศาสตร์เล็กน้อยคุณสามารถกำหนดพารามิเตอร์เริ่มต้นที่จะเข้าถึงกลุ่มเป้าหมาย - แม้เป็นกลุ่มที่เคลื่อนไหวได้ถ้ามันสามารถคาดเดาได้
XNA ยังมีฟังก์ชั่นการแก้ไขและการเคลื่อนไหวโค้งจำนวนมาก ลองดูที่เป็นเอกสารVector2
และ MathHelper
เหล่านี้มีฟังก์ชั่นการแก้ไขบางอย่างที่คุณสามารถใช้และรวมเข้าด้วยกันเพื่อทำสิ่งที่น่าสนใจ ตัวอย่างเช่นการยิงขีปนาวุธ: Lerp
(สอดแทรกเชิงเส้น) ตำแหน่งของขีปนาวุธของคุณจากจุดเริ่มต้นไปยังตำแหน่งเป้าหมายและยังลอบวางตำแหน่งเป้าหมายจากเป้าหมายเริ่มต้นไปยังตำแหน่งที่แท้จริง (เปลี่ยน) ของวัตถุเป้าหมาย สิ่งนี้จะให้เอฟเฟกต์ "ล็อค" ที่ดี
(นอกจากนี้ยังมีฟังก์ชั่นบางอย่างสำหรับการสร้างส่วนโค้งเช่น: CatmulRom
, Hermite
. เหล่านี้อาจใช้งานได้ยากกับเป้าหมายที่เคลื่อนที่ได้)
หากคุณดูที่ "ผ่อนคลาย" (ในบริบทของภาพเคลื่อนไหว) คุณสามารถรับฟังก์ชั่นการแก้ไขที่น่าสนใจซึ่งสามารถให้เอฟเฟกต์ที่น่าสนใจเช่นการเร่งความเร็ว
ตอนนี้ - คุณอาจบอกว่าเทคนิคนี้ให้ผลลัพธ์แปลก ๆ ตามที่คุณต้องการ อย่างไรก็ตามในทางปฏิบัติตราบใดที่กระสุนปืนของคุณเคลื่อนที่เร็วกว่าเป้าหมายของคุณก็มักจะดูดี หากเป็นปัญหาคุณควรใช้เทคนิคเฟรมแทน
คุณอาจต้องการที่จะมองขึ้นคลื่นไซน์หรืออาจจะเป็นเส้นโค้งเบซิเยร์ ฉันไม่รู้ว่าคลื่นไซน์นั้นเป็นเรื่องปกติหรือไม่ แต่ฉันไม่สามารถเห็นได้ว่าทำไมมันถึงแย่
คุณสามารถดูพฤติกรรมของพวงมาลัยได้ตามที่กำหนดโดย Craig Reynolds: http://red3d.com/cwr/steer/
มักใช้ใน AI เพื่อให้ NPC เคลื่อนที่ไปยังเป้าหมายของพวกเขา