Mengingat konteks pertanyaan Anda, http://nodewar.com/ , ada beberapa pertimbangan khusus untuk solusi Anda:
- Anda memiliki kecepatan sudut maksimum (rendah), dan torsi maksimum yang cukup untuk mencapainya dalam waktu yang sangat singkat.
- Drone dan target Anda masing-masing memiliki kecepatan dan akselerasi eksternal yang tidak terkait dengan daya dorong (gravitasi berlimpah).
- Target yang Anda inginkan berubah begitu sering sehingga berusaha membidik dengan sempurna akan sia-sia. Anda harus mencoba mendekat, dan memperbaikinya setiap frame.
Metode ini adalah apa yang saya tekankan untuk bekerja untuk mencapai akselerasi yang diinginkan.
Akselerasi, bukan kecepatan
Karena Anda sudah memiliki kecepatan tertentu, dan target Anda bergerak, Anda tidak perlu didorong ke suatu titik. Anda perlu dorongan untuk mengubah kecepatan Anda menjadi seperti seharusnya. Ini berarti bahwa kapal Anda perlu menunjuk bukan ke arah ke mana ia pergi, tetapi ke arah di mana ia harus mempercepat.
// My target velocity is for maintaining a circular orbit. Yours may differ.
// Earlier, I calculated total gravity and the perpendicular direction.
// You may wish to subtract gravity from your total, rather than match it.
var targetVel = o.lib.vec.times(lateralDir, targetVelMag);
var targetAccel = lv.sum(
o.lib.vec.diff(targetVel, o.me.vel),
o.lib.vec.times(gravity, 1 / o.me.mass)
);
Kemudi ke arah kanan
Anda memiliki vektor percepatan, sekarang Anda ingin menerapkannya. Tentukan seberapa jauh Anda perlu memutar. Saya mungkin menggunakan lebih banyak langkah daripada yang diperlukan di sini, tetapi koordinat rotasi membingungkan saya, dan saya pikir nilai rotasi kapal yang belum dibuka adalah bug di API.
// convert acceleration to an angle
var polar = o.lib.vec.toPolar(targetAccel);
var traj = polar[1];
// constrain the angle to +/-2PI, because the ship's rotation is not limited
// by default
var fixed_rot = o.lib.ang.rescale(o.me.rot);
// limit the correction to be +/-1PI
var traj_correction = traj - fixed_rot;
if (traj_correction > (Math.PI)){
traj_correction = (2 * Math.PI) - traj_correction;
} else if (traj_correction < (-1 * Math.PI)){
traj_correction = (2 * Math.PI) + traj_correction;
}
Formula sederhana. Tidak ada salahnya memutar sepanjang waktu, jadi jangan repot-repot menerapkan nilai torsi parsial. Jika Anda memerlukan koreksi kecil dalam kecepatan sudut, Anda harus membuat penentuan ini berkali-kali per detik.
if (traj_correction > 0){
torque = 1;
} else if (traj_correction < 0){
torque = -1;
}
Formula yang kurang sederhana. Akan ada titik di mana Anda tidak ingin terus berputar, karena Anda akhirnya ingin berhenti. Untungnya, tutup kecepatan sudut itu berarti Anda dapat dengan cepat memperlambat dari kecepatan sudut maks ke nol. Anda hanya perlu menghitung kapan melakukannya.
var max_a_accel = c.MAX_TORQUE / o.me.m_i;
var a_deccel_time = Math.abs(o.me.a_vel) / max_a_accel;
// the same math as linear acceleration, now in angles.
var stopping_angle = 0.5 * max_a_accel * a_deccel_time * a_deccel_time;
if (stopping_angle >= Math.abs(traj_correction)){
// slowdown required. Reverse torque
torque *= -1;
}
Setelah mengubah kode di atas sesuai dengan kebutuhan Anda, kapal Anda harus berputar dengan cepat dan tepat ke sudut mana pun yang Anda berikan untuk ditargetkan.
Kecepatan serudukan
Jadi, kapan harus disodorkan? Sekali lagi, perubahan yang cepat dari target dan faktor-faktor lain menciptakan kesulitan besar dalam menyelesaikan solusi yang tepat. Jangan coba-coba.
// if the heading is close to the final value, thrust.
if (Math.abs(traj_correction ) < 0.02) { // about 1 degree
if (true
// some logical test, in case you don't want to accelerate past
// a maximum speed, or some such. Not required for your stated purpose.
){
thrust = 1;
}
}
Untuk kasus-kasus di mana Anda memerlukan dorongan parsial, Anda dapat kembali mengandalkan fakta bahwa Anda dapat memilih antara 0 dan 1 dorongan berkali-kali per detik. Ini memberi Anda dorongan parsial yang efektif tanpa memvariasikan nilai sebenarnya.
Semoga berhasil!