Ворог рух по прямій лінії до гравця у грі в гонитві


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 ), але у моїх спроб впровадження виникає та сама проблема. Як змусити ворогів рухатися по прямій лінії?

Відповіді:


17

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

При двовимірному русі використовуйте завжди вектори. Це зробить усі речі за вас. Іноді алгебра просто чудова.

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

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

Напевно буде якийсь клас vector2D для вашої цільової мови точно.


Це спрацювало чудово. Нормалізація була потрібною мені функцією. Дякую.
user4761

9

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

Векторне пояснення Нотабене є правильним, але ось як це працює. Vec2d матиме x та y компонент. У наведеному вище прикладі playerPos - neprijateljPos дасть вам вектор (20, 10). normalize () змінює вектор так, що довжина дорівнює 1. В даний час довжина sqrt (20 * 20 + 10 * 10). Це приблизно 22.36068. нормалізація ділить і 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, допомагають мені працювати в грі. Дякую.
user4761
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.