В свете контекста вашего вопроса, http://nodewar.com/ , есть несколько конкретных соображений для вашего решения:
- У вас есть (низкая) максимальная угловая скорость и достаточный максимальный крутящий момент, чтобы достичь ее за очень короткое время.
- Ваш дрон и цель имеют скорость и внешнее ускорение, не связанные с тягой (гравитация в изобилии).
- Ваша желаемая цель меняется так часто, что попытка прицелиться идеально будет пустой тратой. Вы должны попытаться подобраться ближе и исправить это каждый кадр.
Именно эти методы я решил использовать для достижения желаемого ускорения.
Ускорение, а не скорость
Поскольку у вас уже есть заданная скорость, и ваша цель движется, вам не нужно тянуть к точке. Вам нужно тягу, чтобы изменить свою скорость до того, что должно быть. Это означает, что ваш корабль должен указывать не туда, куда он движется, а в направлении, в котором он должен ускоряться.
// 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)
);
Направление в правильном направлении
У вас есть вектор ускорения, теперь вы хотите применить его. Определите, как далеко вы должны повернуть. Возможно, я использовал больше шагов, чем требовалось, но координаты вращения меня смущают, и я думаю, что значение вращения корабля без колпачка в любом случае является ошибкой в 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;
}
Простая формула. Поворот все время не причиняет вреда, поэтому не пытайтесь применять значения частичного крутящего момента. Если вам нужна небольшая коррекция угловой скорости, вы все равно будете делать это определение много раз в секунду.
if (traj_correction > 0){
torque = 1;
} else if (traj_correction < 0){
torque = -1;
}
Менее простая формула. Наступит момент, когда вы не захотите продолжать разворачиваться, потому что в конце концов захотите остановиться. К счастью, этот предел угловой скорости означает, что вы можете быстро снизить скорость от максимальной угловой скорости до нуля. Вам нужно только рассчитать, когда это сделать.
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;
}
После настройки приведенного выше кода в соответствии с вашими потребностями ваш корабль должен быстро и точно поворачиваться на любой угол, который вы указали для цели.
Скорость тарана
Так когда же засунуть? Опять же, быстрое изменение цели и другие факторы создают большие трудности в поиске точного решения. Не пытайся
// 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;
}
}
В тех случаях, когда вам нужна частичная тяга, вы снова можете рассчитывать на то, что вы можете выбирать между 0 и 1 ударом много раз в секунду. Это дает вам эффективную частичную тягу без изменения фактического значения.
Удачи!