À la lumière du contexte de votre question, http://nodewar.com/ , il existe quelques considérations spécifiques pour votre solution:
- Vous avez une vitesse angulaire maximale (faible) et un couple maximum suffisant pour l'atteindre en très peu de temps.
- Votre drone et votre cible ont chacun une vitesse et une accélération externe sans rapport avec la poussée (la gravitation abonde).
- Votre objectif souhaité change si souvent que tenter de viser parfaitement serait un gaspillage. Vous devriez essayer de vous rapprocher et de le corriger à chaque image.
Ces méthodes sont ce que j'ai décidé de travailler pour atteindre l'accélération souhaitée.
Accélération, pas vitesse
Parce que vous avez déjà une vitesse donnée et que votre cible se déplace, vous n'avez pas besoin de poussée vers un point. Vous avez besoin de poussée pour changer votre vitesse à ce qu'elle devrait être. Cela signifie que votre vaisseau ne doit pas pointer vers où il va, mais dans la direction dans laquelle il devrait accélérer.
// 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)
);
Direction vers le bon cap
Vous avez un vecteur d'accélération, vous voulez maintenant l'appliquer. Déterminez jusqu'où vous devez tourner. J'ai probablement utilisé plus d'étapes que nécessaire ici, mais les coordonnées de rotation me confondent, et je pense que la valeur de rotation du navire non plafonnée est de toute façon un bug dans l'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;
}
Une formule simple. Il n'y a aucun mal à tourner tout le temps, alors ne vous embêtez pas à appliquer des valeurs de couple partielles. Si vous avez besoin d'une petite correction de la vitesse angulaire, vous pouvez de toute façon effectuer cette détermination plusieurs fois par seconde.
if (traj_correction > 0){
torque = 1;
} else if (traj_correction < 0){
torque = -1;
}
Une formule moins simple. Il arrivera un moment où vous ne voudrez plus continuer à tourner, car vous voudrez éventuellement vous arrêter. Heureusement, ce plafond de vitesse angulaire signifie que vous pouvez rapidement ralentir de la vitesse angulaire maximale à zéro. Il vous suffit de calculer quand le faire.
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;
}
Après avoir modifié le code ci-dessus pour l'adapter à vos besoins, votre vaisseau devrait rapidement et précisément pivoter dans l'angle que vous lui avez donné pour cibler.
Vitesse de battage
Alors, quand pousser? Encore une fois, le changement rapide de la cible et d'autres facteurs créent une grande difficulté à résoudre une solution exacte. N'essayez pas.
// 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;
}
}
Pour les cas où vous avez besoin d'une poussée partielle, vous pouvez à nouveau compter sur le fait que vous pouvez choisir entre 0 et 1 poussée plusieurs fois par seconde. Cela vous donne une poussée partielle efficace sans faire varier la valeur réelle.
Bonne chance!