Движение врага по прямой линии к игроку в погоне

10

Я создаю игру, в которой враги случайно появляются на карте, а затем перемещаются к игроку каждый кадр со случайной скоростью. На карте нет препятствий, поэтому враги всегда должны двигаться по прямой линии. Я написал функцию движения несколько раз, но независимо от того, что враги всегда били в углы 0, 45, 90, 135, 180, 225, 270, 315, но никогда не были прямой линией. Вот пример кода:

    base_speed = random();

    diff_x = abs(enemy_y_pos - player_x_pos);
    diff_y = abs(enemy_x_pos - player_y_pos);
     if (diff_x > diff_y) {
      y_speed = base_speed;
     } else if (diff_y > diff_x) {
      x_speed = base_speed;
     }

     if (enemy_x_pos < player_x_pos) {
      velocity.x = x_speed;
     } else if (enemy_x_pos > player_x_pos) {
      velocity.x = -x_speed;
     } else {
      velocity.x = 0;
     }

     if (enemy_y_pos < player_y_pos) {
      velocity.y = y_speed;
     } else if (enemy_y_pos > player_y_pos) {
      velocity.y = -y_speed;
     } else {
            velocity.y = 0;
    }

    enemy_x_pos = enemy_x_pos + velocity.x;
    enemy_y_pos = enemy_y_pos + velocity.y;

Это моя первая попытка программирования игры. Я предполагаю, что он должен использовать алгоритм, подобный линии Брезенхэма ( http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm ), но мои попытки реализовать имеют ту же проблему. Как заставить врагов двигаться по прямой линии?

user4761
источник

Ответы:

17

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

При выполнении 2D-движения всегда используйте векторы. Это сделает все для вас. Иногда алгебра просто замечательна.

Vec2d playerPos;
Vec2d direction; // always normalized
float velocity;

update()
{
   direction = normalize(playerPos - enemyPos);
   playerPos = playerPos + direction * velocity;
}

Для вашего целевого языка наверняка будет класс vector2D.

NotaBene
источник
Это сработало отлично. Нормализация была той функцией, которая мне была нужна. Спасибо.
user4761
9

Вы рассчитываете каждый кадр? Ваш код устанавливает либо x_speed, либо y_speed в случайное число, а другой в ноль (или по умолчанию). Допустим, враг находится в 0, 0, а игрок в 20, 10. Похоже, что он будет устанавливать x_speed на случайное число в каждом кадре и перемещать противника вправо, пока он не достигнет 10, 0. Затем враг будет двигаться либо х, либо у каждого кадра, так что будет казаться, что он движется под углом 45 градусов до 10, 10.

Векторное объяснение Нотабене верно, но вот как это работает. Vec2d будет иметь компонент x и y. В приведенном выше примере playerPos - врагаPos даст вам вектор (20, 10). normalize () изменяет вектор так, что длина равна 1. В настоящее время длина равна sqrt (20 * 20 + 10 * 10). Это около 22,36068. normalize делит и X, и Y на это число, давая вам примерно (0,89443, 0,44721) для направления, которое представляет собой вектор, указывающий от противника на игрока с длиной 1. Умножение этого значения на вашу произвольную скорость делает то, что вы хотите.

Однако я бы не рассчитывал новую случайную скорость каждого кадра. Вы, вероятно, просто хотите установить случайную скорость один раз или иметь начальную скорость и целевую скорость, которые вы приближаете к каждому кадру. Ваш противник не имеет смысла сначала развивать скорость 100 миль в час, затем 50 миль в час на один кадр и 200 миль в час на следующий.

float targetSpeed = random(); // do this only rarely, or each frame if you don't mind slowing down and speeding up constantly

float acceleration = max(abs(targetSpeed - speed), 0.5) * sgn(targetSpeed - speed); // cap accel/decel at 0.5 per frame
speed = speed + acceleration;
Джейсон Гомаат
источник
Приятные объяснения и дополнения Джейсон, спасибо. Мне нравится твоя функция ускорения
Notabene
random () в этой области был опечаткой. Ваше объяснение и код с тем, что написал notabene, помогают мне заставить игру работать. Спасибо.
user4761