Все, что вам нужно сделать, это ограничить скорость скорости противника.
// Calculate velocity just as you're doing it
var p = .00005;
var velx = distx * p;
var vely = disty * p;
// Rate limit that velocity
var maxVel = 5; // You will have to tune this value as your max speed
var vel = Math.sqrt(velx*velx + vely*vely);
if (vel > maxVel) {
var r = maxVel / vel;
velx *= r;
vely *= r;
}
// Move the enemy
moveX += velx;
moveY += vely;
В сущности, вы реализуете только «пропорциональную» часть того, что инженеры систем управления (1) называют ПИД-регулятором . Вы хотите, чтобы противник отслеживал игрока, а PID-контроллер - это простой простой tunable
(думаю, враг трудности) контроллер отслеживания.
В ПИД-контроллере для отслеживания вы сначала измеряете ошибку между желаемой целью и текущим состоянием дел. (Вы делаете это сейчас и вызываете переменные distx
и disty
.) В ПИД-контроллере вы сохраняете память о прошлых ошибках, поэтому вы можете действовать по-разному в зависимости от разных точек зрения на ошибку.
PID = function() {
this.p = 0;
this.i = 0;
this.d = 0;
this.reset(0);
};
PID.prototype.reset = function(error) {
this.error = error;
this.integral = 0;
this.differential = 0;
}
PID.prototype.step = function(error) {
this.integral += error;
this.differential = (error - this.error);
this.error = error;
var control = this.p * this.error +
this.i * this.integral +
this.d * this.differential;
return control;
};
Вы создаете PID-контроллер для каждого из контролируемых состояний для объекта, которым вы пытаетесь управлять (противник). Таким образом, ваша логика обновления изменится на:
// distx and disty are calculated as normal
var velx = pidx.step(distx);
var vely = pidy.step(disty);
moveX += velx;
moveY += vely;
Теперь вы можете получать различные виды поведения от врагов, изменяя параметры p,i,d
объекта PID
. Чтобы скопировать ваш текущий ИИ, вы должны установить:
pidx.p = 0.00005;
pidx.i = 0;
pidx.d = 0;
// same for pidy
Хотя более интересного ИИ можно добиться, увеличив параметр i
и уменьшив p
еще больше:
pidx.p = 0.000005;
pidx.i = 0.0005;
pidx.d = 0;
Время от времени вам захочется очистить память врага, если он продержится очень долго. Просто позвоните pidx.reset(distx)
, чтобы сбросить память.
Также вы все равно захотите ограничить скорость velx, vely
, как указано ранее в этом ответе.
Каковы преимущества всей этой сложности? Вы получаете врагов, которые ведут себя очень естественно по сравнению с более простой математикой. Я также хотел отметить, что вы двигаетесь по правильному пути с вашей distx * 0.00005
логикой.
(1) Представьте, что инженеры по контролю - это те, кто изучает поведение закрытых систем и использует эти знания, чтобы заставить систему действовать так, как они хотят.