Öncelikle, taret bakan yönü ile hedefe olan yön arasındaki açı farkını belirlemeniz gerekir.
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;
Bu miktarlara sahip olduğunuzda, taret açısı için ikinci bir derece ifade ayarlayabilirsiniz. Her zaman en son konum ve hız verilerini kullandığınızdan emin olmak için bunu her güncellemede hesaplamanız gerekir.
// Compute angular acceleration.
const float C0 = // Must be determined.
const float C1 = // Must be determined.
float angularAcc = C0 * angleDiff - C1 * turret.angularVelocity;
Burada, ivme ifadesindeki ilk terim (sıfır derece) taretin hedefe doğru dönmeye başlamasına neden olacaktır. Ancak, zaman içinde durmayacak, daha ziyade ileri geri salınacak. Durdurmak için yüksek dönme hızının yüksek bir ivmelenme ile karşı karşıya kalmasına neden olan ikinci terim sönümlemesine (birinci derece) ihtiyacımız var.
Şimdi, sistemin iyi çalışmasını sağlamak için pozitif sabitlerin (mutlaka program sabitleri olması gerekmez) belirlenmesi ve dengelenmesi gerekir. C0
sistemin hızının ana kontrolüdür. İçin yüksek bir değer C0
hızlı bir dönüş hızı sağlayacak ve düşük bir değer düşük bir dönüş hızı sağlayacaktır. Gerçek değer birçok faktöre bağlıdır, bu yüzden burada deneme yanılma kullanmanız gerekir. C1
sönümleme büyüklüğünü kontrol eder. İkinci dereceden denklemin ayırt edici özelliği bize C1*C1 - 4*C0 >= 0
salınım yapmayan bir sistemimiz olduğunu söyler .
// New definition.
const float C1 = 2*sqrt(C0); // Stabilizes the system.
C1
Sayısal nedenlerden ötürü muhtemelen bundan biraz daha büyük bir seçim yapmalısınız , ancak çok büyük değil çünkü bunun yerine aşırı sönümlenir ve yavaş yanıt verebilir. Yine, ince ayar yapmanız gerekir.
Ayrıca, bu kodun yalnızca açısal ivmeyi hesapladığına dikkat etmek önemlidir. Açı ve açısal hız, başka bir yerden, bir çeşit bütünleştirici kullanarak ve bununla güncellenmelidir. Sorudan, bunun ele alındığını varsayıyorum.
Sonunda, gecikme hakkında söylenecek bir şey var, çünkü hızlı bir hedefi takip ederken taret muhtemelen her zaman geride olacak. Bununla baş etmenin basit bir yolu, hedefin konumuna doğrusal bir tahmin eklemek, yani her zaman hedefin ileri yönünde bir miktar ileriye doğru hedeflemektir.
// 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;
/// ...
Hedef yarıçapında hedeflenen tareti bir süre tutmaya gelince, bu doğrudan bu tür bir sisteme dayatılması zor bir gereklilik olabilir. Bu kontrolörün, tareti hedefe (ya da öngörülen pozisyona) yönelik olarak tutmaya çalışacağından emin olabilirsiniz. Sonuç tatmin edici olmadığı ortaya çıkarsa sen parametrelerini değiştirmek zorunda predictionTime
, C0
ve C1
(stabil sınırları içinde).