À luz do contexto da sua pergunta, http://nodewar.com/ , existem algumas considerações específicas para sua solução:
- Você tem uma velocidade angular máxima (baixa) e torque máximo suficiente para alcançá-la em um tempo muito curto.
- Seu drone e seu alvo têm velocidade e aceleração externa não relacionadas ao empuxo (a gravitação é abundante).
- Seu alvo desejado muda com tanta frequência que tentar mirar perfeitamente seria um desperdício. Você deve tentar se aproximar e corrigi-lo em todos os quadros.
Esses métodos são os que eu decidi trabalhar para alcançar a aceleração desejada.
Aceleração, não velocidade
Como você já tem uma velocidade determinada e seu alvo está se movendo, não precisa ser empurrado em direção a um ponto. Você precisa se esforçar para mudar sua velocidade para o que deveria ser. Isso significa que sua nave precisa apontar não para onde está indo, mas na direção em que deve 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)
);
Dirigindo na direção certa
Você tem um vetor de aceleração, agora deseja aplicá-lo. Determine a distância que você precisa girar. Provavelmente usei mais etapas do que o necessário aqui, mas as coordenadas de rotação me confundem e, de qualquer maneira, acho que o valor de rotação de navio sem limite é um bug na 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;
}
Uma fórmula simples. Não há mal em girar o tempo todo, portanto, não se preocupe em aplicar valores de torque parciais. Se você precisar de uma pequena correção na velocidade angular, faça essa determinação muitas vezes por segundo, de qualquer maneira.
if (traj_correction > 0){
torque = 1;
} else if (traj_correction < 0){
torque = -1;
}
Uma fórmula menos simples. Chegará um ponto em que você não deseja continuar girando, porque eventualmente quer parar. Felizmente, esse limite de velocidade angular significa que você pode diminuir rapidamente a velocidade angular máxima para zero. Você só precisa calcular quando fazer isso.
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;
}
Depois de ajustar o código acima para atender às suas necessidades, seu navio deve girar rápida e precisamente para qualquer ângulo que você der ao alvo.
Velocidade de percussão
Então, quando empurrar? Novamente, a mudança rápida do alvo e outros fatores criam grande dificuldade na resolução de uma solução exata. Não tente.
// 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;
}
}
Nos casos em que você precisa de impulso parcial, pode confiar novamente no fato de poder escolher entre 0 e 1 impulso várias vezes por segundo. Isso fornece um impulso parcial efetivo sem variar o valor real.
Boa sorte!