Alla luce del contesto della tua domanda, http://nodewar.com/ , ci sono un paio di considerazioni specifiche per la tua soluzione:
- Hai una velocità angolare massima (bassa) e una coppia massima sufficiente per raggiungerla in brevissimo tempo.
- Il drone e il bersaglio hanno ciascuno velocità e accelerazione esterna non correlate alla spinta (la gravitazione abbonda).
- Il tuo obiettivo desiderato cambia così frequentemente che cercare di mirare perfettamente sarebbe uno spreco. Dovresti provare ad avvicinarti e correggerlo ogni fotogramma.
Questi metodi sono ciò che ho deciso di lavorare per raggiungere un'accelerazione desiderata.
Accelerazione, non velocità
Poiché hai già una determinata velocità e il tuo obiettivo si sta muovendo, non hai bisogno di una spinta verso un punto. Hai bisogno di una spinta per cambiare la tua velocità a quello che dovrebbe essere. Ciò significa che la tua nave non deve puntare verso dove sta andando, ma nella direzione in cui dovrebbe accelerare.
// 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)
);
Sterzare verso la giusta direzione
Hai un vettore di accelerazione, ora vuoi applicarlo. Determina fino a che punto devi ruotare. Probabilmente ho usato più passaggi di quelli richiesti qui, ma le coordinate rotazionali mi confondono e penso che il valore di rotazione della nave non sfruttato sia comunque un bug nell'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;
}
Una formula semplice Non c'è nulla di male nel girare continuamente, quindi non preoccuparti di applicare valori di coppia parziali. Se hai bisogno di una piccola correzione della velocità angolare, puoi comunque prendere questa decisione molte volte al secondo.
if (traj_correction > 0){
torque = 1;
} else if (traj_correction < 0){
torque = -1;
}
Una formula meno semplice. Arriverà un punto in cui non vuoi continuare a girare, perché alla fine vuoi fermarti. Fortunatamente, quel limite di velocità angolare significa che puoi rallentare rapidamente dalla velocità angolare massima a zero. Devi solo calcolare quando farlo.
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;
}
Dopo aver modificato il codice in alto per soddisfare le tue esigenze, la tua nave dovrebbe ruotare rapidamente e con precisione in qualunque angolazione hai assegnato al bersaglio.
Velocità di speronamento
Quindi, quando spingere? Ancora una volta, il rapido cambiamento del bersaglio e altri fattori creano una grande difficoltà nel risolvere una soluzione esatta. Non provarci.
// 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;
}
}
Per quei casi in cui è necessaria una spinta parziale, è possibile fare nuovamente affidamento sul fatto che è possibile scegliere tra 0 e 1 spinta più volte al secondo. Questo ti dà una spinta parziale efficace senza variare il valore reale.
In bocca al lupo!