วิธีการจำลองทางฟิสิกส์แบบใดที่เหมาะสมที่สุดสำหรับเวลาเดลต้าขนาดใหญ่ (ชั่วโมงต่อสัปดาห์)
นอกจากนี้ฉันจะประสบปัญหาใด ๆ ที่รวมวิธีการต่าง ๆ สำหรับเดลต้าใหญ่และเล็กหรือไม่
วิธีการจำลองทางฟิสิกส์แบบใดที่เหมาะสมที่สุดสำหรับเวลาเดลต้าขนาดใหญ่ (ชั่วโมงต่อสัปดาห์)
นอกจากนี้ฉันจะประสบปัญหาใด ๆ ที่รวมวิธีการต่าง ๆ สำหรับเดลต้าใหญ่และเล็กหรือไม่
คำตอบ:
คุณอาจจะใช้การเร่งความเร็วคงที่สำหรับช่วงเวลาขนาดใหญ่เหล่านี้ (ซึ่งอาจเป็นศูนย์การเร่งความเร็ว) อนุพันธ์ของการเร่งความเร็วคงที่เมื่อเทียบกับเวลาคือ 0 นั่นหมายความว่ามันจะไม่เปลี่ยนแปลงตามเวลาดังนั้นมันไม่สำคัญว่าเวลาเดลต้าของคุณจะมีขนาดใหญ่เพียงใด
การบูรณาการเล็กน้อยตามเวลาให้สมการที่คุณต้องการ
a = a
v = at + v0
s = .5at^2 + v0*t + s0
ที่ไหน: a = ความเร่ง, v = ความเร็ว, v0 = ความเร็วเริ่มต้น, s = ตำแหน่ง, s0 = ตำแหน่งเริ่มต้น, t = เวลา
การใช้กลยุทธ์นี้คุณสามารถใช้ช่วงเวลาตั้งแต่มิลลิวินาทีถึงหลายสัปดาห์หากคุณต้องการ รวมพวกเขาจะได้รับการดูแลในv0
และs0
พารามิเตอร์ของสมการ
การชนกันจับคุณจะต้องใช้กลยุทธ์คล้ายกับที่ใช้สำหรับวัตถุขนาดเล็กความเร็วสูง ขั้นแรกให้คำนวณตำแหน่งใหม่โดยใช้สมการข้างต้นจากนั้นกวาดระหว่างตำแหน่งเก่าและใหม่สำหรับวัตถุทั้งหมด เนื่องจากวัตถุใดวัตถุหนึ่งเหล่านั้นสามารถตัดกันซึ่งกันและกัน (นาทีหรือวันก่อน) สิ่งนี้จึงซับซ้อนมาก เป็นไปได้ว่าเมื่อคุณมีเวลาเดลต้าขนาดใหญ่เช่นนี้หวังว่าคุณจะมีเวลาอีกมากในการประมวลผลการชนที่อาจเกิดขึ้นเหล่านี้
ให้ยกตัวอย่างด้วยแรงโน้มถ่วง
ในฟังก์ชั่นด้านล่างสมมติว่าเรามีตัวแปรสมาชิกคลาสสำหรับตำแหน่งและความเร็ว เราจำเป็นต้องอัปเดตเนื่องจากแรงโน้มถ่วงของทุก dt วินาที
void update( float dt )
{
acceleration = G * m / r^2;
velocity = velocity + acceleration * dt;
position = position + velocity * dt;
}
เมื่อdt
ขนาดเล็กลงและเล็กลงการจำลองของเรามีความแม่นยำมากขึ้น (แม้ว่าdt
จะเล็กเกินไปเราก็จะพบข้อผิดพลาดที่แม่นยำเมื่อทำการเพิ่มจำนวนเล็กน้อยให้เป็นจำนวนมาก)
โดยพื้นฐานแล้วคุณต้องตัดสินใจว่าการdt
จำลองของคุณสามารถจัดการได้สูงสุดเพื่อให้ได้ผลลัพธ์ที่ดีพอ และถ้าสิ่งdt
ที่เข้ามามีขนาดใหญ่เกินไปเพียงแค่แบ่งการจำลองลงในขั้นตอนที่เล็กลงโดยที่แต่ละขั้นตอนเป็นจำนวนสูงสุดdt
ที่คุณอนุญาต
void update( float dt )
{
acceleration = G * m / r^2;
velocity = velocity + acceleration * dt;
position = position + velocity * dt;
}
// this is the function we call. The above function is a helper to this function.
void updateLargeDt( float dt )
{
const float timeStep = 0.1;
while( dt > timeStep )
{
update( timeStep );
dt -= timeStep ;
}
update( dt ); // update with whatever dt is left over from above
}
ดังนั้นด้วยกลยุทธ์นี้คุณสามารถปรับtimeStep
ให้เข้ากับสิ่งที่คุณต้องการได้ (ทำให้เป็นวินาทีวินาทีชั่วโมงหรืออะไรก็ตามที่จำเป็นเพื่อให้ได้ฟิสิกส์ที่แม่นยำ
เกมส่วนใหญ่มีแนวโน้มที่จะใช้วิธีการออยเลอร์แบบง่ายของการรวมไปข้างหน้า (นั่นคือรวมความเร็วเข้าไปในตำแหน่งเมื่อเวลาผ่านไปและรวมการเร่งความเร็วเข้ากับความเร็ว) น่าเสียดายที่วิธีการของออยเลอร์เหมาะสำหรับเวลาที่น้อยมากและระยะสั้นเท่านั้น
มีวิธีการที่ซับซ้อนมากขึ้นซึ่งมีความแม่นยำมากขึ้นในระยะเวลาที่ยาวนานมาก ที่นิยมมากที่สุดและง่ายที่สุดในการดำเนินการอาจจะRunge-Kutte-4 RK4 กำหนดตำแหน่งในอนาคตโดยการสุ่มตัวอย่างสี่ตำแหน่งและความเร็วในอดีตและการสอดแทรก มันมีความแม่นยำมากกว่าวิธีออยเลอร์มากกว่าระยะเวลาที่นานกว่า แต่มีราคาสูงกว่าการคำนวณ
ตัวอย่างเช่นหากคุณต้องการคำนวณฟิสิกส์ของดาวเคราะห์ที่โคจรรอบจริงอัปเดตทุก ๆ สองสามวันตามเวลาจริงวิธีการออยเลอร์จะทำให้ดาวเคราะห์ยิงออกสู่อวกาศหลังจากโคจรเพียงไม่กี่ครั้งเนื่องจากข้อผิดพลาดเชิงตัวเลข โดยทั่วไป RK4 จะทำให้ดาวเคราะห์โคจรรอบโลกในรูปแบบเดียวกันหลายพันครั้งก่อนที่จะเกิดข้อผิดพลาดมากเกินไป
อย่างไรก็ตามการใช้การชนเข้ากับ RK4 นั้นเป็นสิ่งที่ท้าทายมาก ...