Ruch wroga w linii prostej do gracza w grze pościgowej


10

Tworzę grę, w której wrogowie pojawiają się losowo na mapie, a następnie przesuwają się w kierunku gracza co klatkę z losową prędkością. Mapa nie ma przeszkód, więc wrogowie powinni zawsze poruszać się w linii prostej. Napisałem funkcję ruchu kilka razy, ale bez względu na to, co wrogowie zawsze uderzają o 0, 45, 90, 135, 180, 225, 270, 315 kątów, ale nigdy nie są linią prostą. Oto przykład kodu:

    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;

To moja pierwsza próba programowania gier. Domyślam się, że powinien on używać algorytmu takiego jak Bresenham's Line ( http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm ), ale moje próby wdrożenia mają ten sam problem. Jak sprawić, by wrogowie poruszali się w linii prostej?

Odpowiedzi:


17

Algorytm linii Bresenhama został opracowany do szybkiego rysowania linii bez użycia operacji zmiennoprzecinkowych (operacje na liczbach całkowitych są szybsze). Jest to bardzo ciekawe historycznie, ale niezbyt dobre rozwiązanie dla gry (szczególnie, ponieważ nie można określić prędkości).

Podczas wykonywania ruchu 2D zawsze używaj wektorów. To wszystko załatwi. Czasami algebra jest po prostu cudowna.

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

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

Na pewno będzie klasa vector2D dla twojego języka docelowego.


To działało idealnie. Normalizacja była funkcją, której potrzebowałem. Dzięki.
user4761,

9

Obliczasz każdą klatkę? Twój kod ustawia albo x_speed, albo y_speed na liczbę losową, a drugą na zero (lub domyślną). Powiedzmy, że wróg ma 0, 0, a gracz ma 20, 10. Wygląda na to, że ustawi x_speed na jakąś losową liczbę w każdej klatce i przesunie wroga w prawo, aż osiągnie 10, 0. Wtedy wróg ruszy się albo x albo y każdej klatki, więc wydaje się, że porusza się pod kątem 45 stopni do 10, 10.

Wyjaśnienie wektora Notabene jest słuszne, ale oto jak to działa. Vec2d będzie miał składnik xiy. W powyższym przykładzie playerPos - wrogiPos da ci wektor o wartości (20, 10). normalize () zmienia wektor tak, że długość wynosi 1. Obecnie długość wynosi sqrt (20 * 20 + 10 * 10). To jest około 22,36068. normalizuj dzieli zarówno X, jak i Y przez tę liczbę, dając ci około (0,89443, 0,44721) dla kierunku, który jest wektorem skierowanym od wroga do gracza o długości 1. Pomnożenie tego przez twoją losową prędkość robi to, czego chcesz.

Jednak nie obliczałbym nowej losowej prędkości dla każdej klatki. Prawdopodobnie zechcesz tylko raz ustawić losową prędkość lub mieć prędkość początkową i docelową, które zbliżają się do każdej klatki. Nie ma sensu, aby twój wróg początkowo przekraczał 100 km / h, następnie 50 km / h dla jednej klatki i 200 km / h dla następnej.

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;

Ładne wyjaśnienia i uzupełnienia, Jason, dzięki. Podoba mi się twoja funkcja przyspieszania
Notabene

random () w tym zakresie był literówką. Twoje wyjaśnienie i kod z tym, co napisał notabene, pomaga mi uruchomić grę. Dzięki.
user4761,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.