Pertama, Anda perlu menentukan perbedaan sudut antara arah turret menghadap dan arah ke target.
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;
Setelah Anda memiliki jumlah ini, Anda dapat mengatur ekspresi derajat kedua untuk sudut turret. Anda perlu menghitung ini pada setiap pembaruan untuk memastikan Anda selalu menggunakan data terbaru dari posisi dan kecepatan.
// Compute angular acceleration.
const float C0 = // Must be determined.
const float C1 = // Must be determined.
float angularAcc = C0 * angleDiff - C1 * turret.angularVelocity;
Di sini, suku pertama (nol derajat) dalam ekspresi akselerasi akan menyebabkan turet mulai berbalik ke arah target. Namun itu tidak akan berhenti tepat waktu tetapi berosilasi bolak-balik di atasnya. Untuk menghentikannya kita membutuhkan peredam istilah kedua (derajat pertama) yang menyebabkan kecepatan belok tinggi ditentang oleh akselerasi tinggi.
Sekarang konstanta positif (tidak harus konstanta program) perlu ditentukan dan seimbang untuk membuat sistem berperilaku baik. C0
adalah kontrol utama untuk kecepatan sistem. Nilai yang tinggi untuk C0
akan memberikan kecepatan belokan cepat dan nilai yang rendah akan memberikan kecepatan belokan yang rendah. Nilai aktual tergantung pada banyak faktor sehingga Anda harus menggunakan coba-coba di sini. C1
mengontrol besarnya redaman. The diskriminan dari persamaan kuadrat memberitahu kita bahwa jika C1*C1 - 4*C0 >= 0
kita memiliki sistem non-berosilasi.
// New definition.
const float C1 = 2*sqrt(C0); // Stabilizes the system.
Anda mungkin harus memilih C1
yang sedikit lebih besar dari ini karena alasan numerik, tetapi tidak terlalu besar karena mungkin akan menjadi terlalu lembab dan lambat untuk merespons. Sekali lagi, Anda perlu mengubah.
Juga penting untuk dicatat bahwa kode ini hanya menghitung percepatan sudut. Sudut dan kecepatan sudut perlu diperbarui dari tempat lain ini, menggunakan dan integrator dari beberapa jenis. Dari pertanyaan saya berasumsi bahwa ini telah dibahas.
Akhirnya ada sesuatu untuk dikatakan tentang lagging, karena turret mungkin akan selalu tertinggal ketika melacak target yang cepat. Cara sederhana untuk mengatasi ini adalah dengan menambahkan prediksi linier ke posisi target, yaitu selalu mengarah sedikit ke depan dalam arah maju target.
// 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;
/// ...
Adapun untuk menjaga turet diarahkan dalam radius target untuk beberapa waktu, ini mungkin merupakan persyaratan yang sulit untuk memaksakan langsung pada sistem semacam ini. Anda dapat yakin bahwa pengontrol ini akan berusaha untuk menjaga turet diarahkan pada target (atau lebih tepatnya posisi yang diprediksi) setiap saat. Jika hasilnya ternyata tidak memuaskan Anda harus memodifikasi parameter predictionTime
, C0
dan C1
(dalam batas stabil).