A la luz del contexto de su pregunta, http://nodewar.com/ , hay un par de consideraciones específicas para su solución:
- Tiene una velocidad angular máxima (baja) y suficiente par máximo para alcanzarla en muy poco tiempo.
- Tu dron y objetivo tienen velocidad y aceleración externa no relacionadas con el empuje (abunda la gravitación).
- Su objetivo deseado cambia con tanta frecuencia que tratar de apuntar perfectamente sería un desperdicio. Debes intentar acercarte y corregirlo en cada cuadro.
Estos métodos son los que decidí trabajar para alcanzar la aceleración deseada.
Aceleración, no velocidad
Como ya tiene una velocidad determinada y su objetivo se está moviendo, no necesita empujar hacia un punto. Necesita empuje para cambiar su velocidad a lo que debería ser. Esto significa que su nave necesita apuntar no hacia dónde va, sino en la dirección en la que debe acelerar.
// 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)
);
Dirección hacia la derecha
Tienes un vector de aceleración, ahora quieres aplicarlo. Determine qué tan lejos necesita rotar. Probablemente usé más pasos de los requeridos aquí, pero las coordenadas de rotación me confunden, y creo que el valor de rotación de la nave sin tapar es un error en la API de todos modos.
// 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;
}
Una formula simple. No hay daño en girar todo el tiempo, así que no se moleste en aplicar valores par parciales. Si necesita una pequeña corrección en la velocidad angular, puede hacer esta determinación muchas veces por segundo, de todos modos.
if (traj_correction > 0){
torque = 1;
} else if (traj_correction < 0){
torque = -1;
}
Una fórmula menos simple. Llegará un punto en el que no querrás seguir girando, porque eventualmente quieres detenerte. Afortunadamente, ese límite de velocidad angular significa que puede reducir rápidamente la velocidad angular máxima a cero. Solo necesita calcular cuándo hacerlo.
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;
}
Después de ajustar el código anterior para satisfacer sus necesidades, su nave debe rotar rápida y precisamente a cualquier ángulo que le haya dado al objetivo.
Velocidad de embestida
Entonces, ¿cuándo empujar? Nuevamente, el rápido cambio del objetivo y otros factores crean una gran dificultad para resolver una solución exacta. No lo intentes
// 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;
}
}
Para aquellos casos en los que necesita un empuje parcial, puede confiar nuevamente en el hecho de que puede elegir entre 0 y 1 empuje muchas veces por segundo. Esto le proporciona un empuje parcial efectivo sin variar el valor real.
¡Buena suerte!