Зважаючи на контекст вашого питання, 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 поштовхом багато разів на секунду. Це дає ефективну часткову тягу без зміни фактичного значення.
Удачі!