Projectile Motion - ลูกศร


13

ในเกม 2D ฉันเพียงต้องการวาดวิถีลูกศรในการบิน ด้วยรหัสด้านล่างวิถี (พาราโบลา) ดูขวา แต่มุม (หรือการหมุน) หรือลูกศรไม่ได้

float g = -9.8f;
float x = (launchVelocity * time);
float y = (launchVelocity * time) + (0.5f * g * (float)Math.Pow(time, 2));
float angle = (float)Math.Tanh(y / x);

ฉันกำลังคิดถึงอะไร ขอบคุณ


3
ภาพหน้าจออาจช่วยได้
doppelgreener

คำตอบ:


10

Arctanhให้แทนเจนต์สำหรับส่วนโค้งไฮเพอร์โบลิก! เท่าที่ฉันรู้พาราโบลาของคุณไม่ใช่ไฮเปอร์โบลา

แต่เรามีข่าวดี: การหาแทนเจนต์สำหรับพาราโบลาของคุณนั้นง่ายกว่า สมการคือ

x = s · t => t = x / s; y = s · t + g / 2 ·t² => y = x + g / 2 ·x² / s²

launchVelocityไหนคือของคุณ ทีนี้ความชันของลูกศรของคุณคือ:

∂y / ∂y = g / (2s²) · x + 1

คุณสามารถใช้ความปลอดภัยได้ทันทีArctanหากต้องการ

ข้อมูลเพิ่มเติมบางอย่างเกี่ยวกับฟิสิกส์:

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

โปรดจำไว้ว่าคุณไม่ได้พิจารณาโมเมนตัมเฉื่อยของลูกศร (ซึ่งอาจแตกต่างกันมากหากคุณกำลังยิง ballista ยักษ์) และคุณไม่ได้พิจารณาการเคลื่อนที่ของของเหลวของลูกศร: การบินธนูลูกศรจะไม่ไปตามเส้นทางที่เป็นรูปโค้ง!


ขอบคุณ Fxlll ความคิดใดที่ฉันสามารถรับสูตรที่ใช้กับลูกศรของฟิสิกส์ได้
Martin

ฉันคิดว่าคุณหมายถึง:! [& part; y / & part; x = g / (2s & sup2;) & middot; x + 1] [2] แต่ในกรณีใด ๆ ฉันคิดว่าฉันแนะนำวิธีที่ดีกว่าด้านล่าง สำหรับสิ่งหนึ่งคุณไม่ได้อธิบายเกี่ยวกับการแยกส่วนประกอบ x และ y ดังนั้นนี่คือฮาร์ดโค้ดที่มีมุม 45 องศาโดยพลการโดยที่ launchVelocity ไม่ได้ถูกเรียกใช้อย่างแท้จริงความเร็ว แต่องค์ประกอบทั้งใน x และ y
Dov

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

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

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

4

คุณต้องการมุมของลูกศร ณ จุดใดก็ได้ คุณจำได้ว่าในการคำนวณมุมมันมีแทนเจนต์ แต่นี่คือสิ่งที่ความคิดของคุณเริ่มผิดไป:

  1. สิ่งที่คุณต้องการคือเดลต้า y / เดลต้า x เนื่องจากความชันคืออัตราการเปลี่ยนแปลง (กล่าวถึงในคำตอบอื่น) โปรดทราบว่า x เป็นเพียงตำแหน่งที่คุณอยู่ในเวลาใดก็ได้ไม่ใช่ dx

ตกลงดังนั้นถ้าคุณละเลยความเสียดทานในอากาศแล้วความเร็ว x ของลูกศรจะคงที่

ขั้นแรกให้แยกความเร็วออกเป็นองค์ประกอบ x และ y คุณสามารถถ่ายทำมุม 45 องศาหรือ 60 องศา ดังนั้นคุณต้องเปิดตัวความเร็วและมุมไม่ใช่สเกลาร์

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

ประการที่สามอย่าใช้ Math.pow มันช้าและไม่แม่นยำเท่าการคูณสำหรับจำนวนเต็ม นอกจากนี้คุณสามารถประหยัดเวลาได้มากโดยใช้แบบฟอร์มของ Horner (ดูด้านล่าง)

final double DEG2RAD = Math.PI/180;
double ang = launchAngle * DEG2RAD;
double v0x = launchVelocity * cos(ang); // initial velocity in x
double v0y = launchVelocity * sin(ang); // initial velocity in y

double x = (v0x * time);
// double y = (v0y * time) + (0.5 * g * (float)Math.Pow(time, 2));
double y = (0.5 * g * time + v0y) * time

หากคุณต้องการประสิทธิภาพคุณสามารถ precompute 0.5 * g แต่โค้ดข้างต้นจะนำคุณไป 90% จากที่นั่นโดยไม่ต้องทำอะไรบ้าไป เกณฑ์มาตรฐานที่ทำเช่นนี้ 10 ล้านครั้งถ้าคุณชอบมันเป็นที่ยอมรับไม่มากนัก แต่เปอร์เซ็นต์ที่ฉลาดก็ค่อนข้างใหญ่ - ห้องสมุดช้ามากใน Java

ดังนั้นหากคุณต้องการมุมที่ลูกศรควรไปสิ่งที่คุณต้องการคือ

atan(dy/dx)

และในกรณีนี้นั่นจะใช้ได้เพราะ dx เป็นค่าคงที่ แต่โดยทั่วไป dx อาจเป็นศูนย์ดังนั้นคุณมักจะต้องการใช้:

atan2(dy, dx)

ซึ่งเป็นฟังก์ชันที่ออกแบบมาสำหรับงานนี้โดยเฉพาะ

แต่อย่างที่ฉันบอกว่าฟังก์ชั่นห้องสมุดใน Java นั้นช้ามากและในกรณีนี้มีวิธีที่ดีกว่าในการทำโดยไม่ต้องพูดถึง @FxIII ด้านบน

หากความเร็วแนวนอนเป็น v0x เสมอและความเร็วแนวตั้งคือ:

double vy = v0y - 0.5 * g * time;

ดังนั้นเดลต้าของคุณคือ: vx, vy

คุณไม่ต้องการมุม หากคุณต้องการวาดลูกศรให้ใช้สิ่งที่มีชื่อเช่น:

พล็อต (x, y, x + vx, y + vy);

ฉันไม่รู้ว่าคุณกำลังวาดอะไรดังนั้นถ้าคุณต้องการมุมเพื่อหมุนมัน (เช่นคุณกำลังใช้ JOGL) แน่นอนว่าใช้มุมนี้

อย่าลืมว่าคุณกำลังใช้ OpenGL เพื่อเปลี่ยนมุมกลับเป็นองศาเพราะ ATAN2 ส่งคืนเรเดียน:

final double RAD2DEG = 180 / Math.PI;
double ang = Math.atan2(vy,vx); // don't forget, vy first!!!
double deg = ang * RAD2DEG;

2

Tanh () (ไฮเพอร์โบลิกแทนเจนต์ ) รับมุมเป็นพารามิเตอร์ แต่คุณป้อนอัตราส่วนของด้านข้าง

สิ่งที่คุณต้องการคือการใช้ไฮเพอร์โบลิกอาร์แทนเจนต์ซึ่งใช้อัตราส่วนของด้านเป็นพารามิเตอร์และคืนค่ามุม (การตั้งชื่อนี้อาจเป็น "atanh", "atanh2", "arctanh" หรืออย่างอื่นที่คล้ายกัน; ดูเหมือนจะแตกต่างกันมากระหว่างห้องสมุดคณิตศาสตร์ที่แตกต่างกัน)


ไม่คุณไม่ต้องการอะไรที่เกินความจริง
Dov

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

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