ก่อนอื่นคุณต้องพิจารณาความแตกต่างของมุมระหว่างป้อมปืนหันหน้าเข้าหาทิศทางและทิศทางไปยังเป้าหมาย
Vector2 turretToTarget = target.position - turret.position;
float desiredAngle = atan2(turretToTarget.y, turretToTarget.x);
float angleDiff = desiredAngle - turret.angle;
// Normalize angle to [-PI,PI] range. This ensures that the turret
// turns the shortest way.
while (angleDiff < -PI) angleDiff += 2*PI;
while (angleDiff >= PI) angleDiff -= 2*PI;
เมื่อคุณมีปริมาณเหล่านี้คุณสามารถตั้งค่านิพจน์ระดับที่สองสำหรับมุมป้อมปืน คุณต้องคำนวณสิ่งนี้ในการอัพเดทแต่ละครั้งเพื่อให้แน่ใจว่าคุณใช้ข้อมูลตำแหน่งและความเร็วล่าสุดเสมอ
// Compute angular acceleration.
const float C0 = // Must be determined.
const float C1 = // Must be determined.
float angularAcc = C0 * angleDiff - C1 * turret.angularVelocity;
ที่นี่เทอมแรก (ศูนย์องศา) ในการแสดงความเร่งจะทำให้ป้อมปืนเริ่มหันเข้าหาเป้าหมาย อย่างไรก็ตามมันจะไม่หยุดในเวลา แต่ค่อนข้างจะแกว่งไปมา ในการทำให้หยุดเราต้องใช้เทอมที่สอง (ระดับแรก) ซึ่งทำให้ความเร็วในการเลี้ยวสูงถูกต่อต้านโดยการเร่งความเร็วสูง
ตอนนี้ค่าคงที่บวก (ไม่จำเป็นต้องเป็นค่าคงที่ของโปรแกรม) จำเป็นต้องได้รับการพิจารณาและสมดุลเพื่อให้ระบบทำงานได้ดี C0
เป็นตัวควบคุมหลักสำหรับความเร็วของระบบ ค่าที่สูงสำหรับC0
จะให้ความเร็วในการเปลี่ยนที่รวดเร็วและค่าต่ำจะให้ความเร็วในการกลึงต่ำ ค่าจริงขึ้นอยู่กับหลายปัจจัยดังนั้นคุณควรใช้การทดลองและข้อผิดพลาดที่นี่ C1
ควบคุมขนาดการทำให้หมาด ๆ การเลือกปฏิบัติของสมการกำลังสองบอกเราว่าถ้าC1*C1 - 4*C0 >= 0
เรามีระบบที่ไม่สั่น
// New definition.
const float C1 = 2*sqrt(C0); // Stabilizes the system.
คุณควรเลือกC1
ใหญ่กว่านี้เล็กน้อยด้วยเหตุผลเชิงตัวเลข แต่ไม่ใหญ่เกินไปเพราะอาจทำให้ชื้นมากและตอบสนองช้า อีกครั้งคุณต้องปรับแต่ง
นอกจากนี้โปรดทราบว่ารหัสนี้คำนวณการเร่งความเร็วเชิงมุมเท่านั้น ความเร็วและมุมเชิงมุมต้องได้รับการอัปเดตจากที่อื่นโดยใช้และผู้รวมระบบในบางประเภท จากคำถามที่ฉันคิดว่าสิ่งนี้ได้รับการคุ้มครอง
ในที่สุดก็มีบางสิ่งที่จะพูดเกี่ยวกับการล้าหลังเพราะป้อมอาจจะอยู่ข้างหลังเสมอเมื่อติดตามเป้าหมายที่รวดเร็ว วิธีง่ายๆในการแก้ไขปัญหานี้คือการเพิ่มการทำนายเชิงเส้นให้กับตำแหน่งของเป้าหมายนั่นคือเล็งไปข้างหน้าเล็กน้อยในทิศทางไปข้างหน้าของเป้าหมาย
// Improvement of the first lines above.
const float predictionTime = 1; // One second prediction, you need to experiment.
Vector2 turretToTarget = target.position + predictionTime * target.velocity - turret.position;
/// ...
สำหรับการรักษาป้อมปืนเล็งไว้ในรัศมีของเป้าหมายในบางครั้งนี่อาจเป็นข้อกำหนดที่ยากมากที่จะกำหนดโดยตรงกับระบบประเภทนี้ คุณสามารถมั่นใจได้ว่าคอนโทรลเลอร์นี้จะพยายามรักษาป้อมปืนไว้ที่เป้าหมาย (หรือมากกว่าตำแหน่งที่คาดการณ์ไว้) ตลอดเวลา หากผลที่เปิดออกไม่ได้เป็นที่น่าพอใจมีการปรับเปลี่ยนพารามิเตอร์predictionTime
, C0
และC1
(ภายในขอบเขตที่มีเสถียรภาพ)