2 объекта следуют друг за другом, но расстояние разделяет их - PullRequest
2 голосов
/ 13 января 2010

В основном я делаю игру, в которой противник идет за героем, когда он находится в поле зрения. Что я делаю для достижения этой цели

var distx = hero.px - px;
var disty = hero.py - py;


moveX += distx * .00005;
moveY += disty * .00005;

Теперь мне пришлось умножить его на .00005, потому что все, что выше, заставляет его довольно быстро подойти к герою. Я хочу, чтобы противник двигался медленно, поэтому я умножил его на 0,00005. Моя проблема в том, что чем дальше они находятся, тем быстрее движется монстр, из-за чего герою становится сложнее уйти. Я знаю, почему это так, мне просто нужно знать, как решить эту проблему.

Я разрабатываю игру, где, если монстр находится слишком далеко, я убираю его со сцены. но проблема уходит. Я хочу, чтобы он двигался с постоянной скоростью, независимо от того, как далеко они друг от друга.

Я также хочу добиться этого, не используя никаких свойств класса. (т.е. я хочу, чтобы все переменные были локальными). Этот метод также находится в цикле

Что я делаю не так? и каковы решения.

Спасибо, ребята

Ответы [ 5 ]

7 голосов
/ 13 января 2010

Все, что вам нужно сделать, это ограничить скорость скорости противника.

// 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) Представьте, что инженеры по контролю - это те, кто изучает поведение закрытых систем и использует эти знания, чтобы заставить систему действовать так, как они хотят.

3 голосов
/ 13 января 2010

Используйте некоторую тригонометрию, чтобы вычислить угол, который вы хотите переместить, а затем двигаться с постоянной скоростью в этом направлении ...

disty и distx - ноги прямоугольного треугольника, гипотенуза - sqrt (disty disty + distx ditsx). sin (угол) = disty / гипотенуза и cos (угол) = distx / гипотенуза (при условии, что x и y поднимаются вверх и вправо).

var distx = hero.px - px;
var disty = hero.py - py;
var hyp = Math.sqrt(disty*disty + distx*ditsx);
moveX += speed * distx / hyp;
moveY += speed * disty / hyp;
0 голосов
/ 13 января 2010

Что я делаю не так?

По мере продвижения героя и врага расстояние между ними (естественно) становится больше. Затем вы берете часть этого расстояния (1/20000-й, если быть точным) и перемещаете противника по нему. Но это означает, что по мере увеличения или уменьшения расстояния величина перемещения противника соответственно увеличивается или уменьшается.

Как указано в некоторых других ответах, приведенных здесь, вам необходимо выяснить, в каком направлении противник должен двигаться к игроку, а затем переместить его в этом направлении на фиксированную величину (а не на дробную).

0 голосов
/ 13 января 2010

То есть вы хотите установить постоянную скорость и изменять только направление?

var speed = 1;

if (hero.px > px) moveX += speed;
else if (hero.px < px) moveX -= speed;

if (hero.py > py) moveY += speed;
else if (hero.py < py) moveY -= speed;
0 голосов
/ 13 января 2010

Это то, что я придумал, похоже, работает нормально

var distx = hero.px - px;
            var disty = hero.py - py;

            if(Math.abs(distx) > 100 && Math.abs(disty) > 100)
            {
                moveX += distx * .00001;
                moveY += disty * .00001;                
            }
            else
            {
                moveX += distx * .00005;
                moveY += disty * .00005;
            }

, кажется, работает нормально. если есть что-то с меньшим количеством строк, которые я могу использовать, это было бы здорово, но я думаю, что я буду придерживаться чего-то вроде этого

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...