Sorunuzun bağlamı ( http://nodewar.com/) ışığında, çözümünüz için birkaç özel husus vardır:
- (Düşük) bir maksimum açısal hıza ve çok kısa sürede ulaşmak için yeterli maksimum torka sahipsiniz.
- Drone ve hedefinizin her biri, itme ile ilişkili olmayan hız ve dış ivmeye sahiptir (yerçekimi bolluğu).
- İstediğiniz hedef o kadar sık değişir ki, mükemmel bir şekilde nişan almayı denemek israf olacaktır. Yaklaşmaya ve her kareyi düzeltmeye çalışmalısınız.
Bu yöntemler, istenen bir ivmeye ulaşmak için çalışmaya karar verdim.
Hız değil, hızlanma
Zaten belirli bir hıza sahip olduğunuz ve hedefiniz hareket ettiği için bir noktaya doğru itmeye ihtiyacınız yok. Hızınızı olması gereken şeye değiştirmek için itmeye ihtiyacınız var. Bu, geminizin gittiği yere değil, hızlanacağı yöne bakması gerektiği anlamına gelir.
// 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)
);
Doğru istikamete yönlendirme
Bir hızlanma vektörünüz var, şimdi uygulamak istiyorsunuz. Ne kadar döndürmeniz gerektiğini belirleyin. Muhtemelen burada gerekenden daha fazla adım kullandım, ancak dönme koordinatları beni şaşırtıyor ve bence kapaksız gemi dönüş değeri zaten API'de bir hata.
// 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;
}
Basit bir formül. Her zaman dönmenin bir zararı yoktur, bu nedenle kısmi tork değerlerini uygulamaktan çekinmeyin. Açısal hızda küçük bir düzeltmeye ihtiyacınız varsa, bu belirlemeyi yine de saniyede birçok kez yapabilirsiniz.
if (traj_correction > 0){
torque = 1;
} else if (traj_correction < 0){
torque = -1;
}
Daha az basit bir formül. Dönmeye devam etmek istemediğiniz bir nokta gelecek, çünkü sonunda durmak istiyorsunuz. Neyse ki, bu açısal hız sınırı, maksimum açısal hızdan sıfıra hızla yavaşlayabileceğiniz anlamına gelir. Sadece ne zaman yapacağınızı hesaplamanız gerekir.
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;
}
Yukarıdaki kodu ihtiyaçlarınıza göre ayarladıktan sonra, geminiz hızlı ve hassas bir şekilde hedefe verdiğiniz açıya dönmelidir.
Çakma hızı
Peki, ne zaman itmeli? Yine, hedefin ve diğer faktörlerin hızlı değişimi, kesin bir çözümü çözmede büyük zorluk yaratır. Denemeyin.
// 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;
}
}
Kısmi itme gerektiren durumlarda, yine saniyede birçok kez 0 ile 1 itme arasında seçim yapabileceğinize güvenebilirsiniz. Bu, gerçek değeri değiştirmeden etkili bir kısmi itme sağlar.
İyi şanslar!