Feindliche Bewegung in gerader Linie zum Spieler im Verfolgungsspiel

10

Ich erstelle ein Spiel, in dem die Feinde zufällig auf einer Karte erscheinen und sich dann in jedem Frame mit zufälliger Geschwindigkeit auf den Spieler zubewegen. Die Karte hat keine Hindernisse, daher sollten sich die Feinde immer in einer geraden Linie bewegen. Ich habe die Bewegungsfunktion ein paar Mal geschrieben, aber egal, was die Feinde immer getroffen haben, 0, 45, 90, 135, 180, 225, 270, 315 Winkel, aber niemals eine gerade Linie. Hier ist ein Beispiel für den Code:

    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;

Dies ist mein erster Versuch, Spiele zu programmieren. Ich denke, es sollte ein Algorithmus wie Bresenham's Line ( http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm ) verwendet werden, aber meine Implementierungsversuche haben das gleiche Problem. Wie bewege ich Feinde in einer geraden Linie?

user4761
quelle

Antworten:

17

Der Linienalgorithmus von Bresenham wurde zum schnellen Zeichnen von Linien ohne Verwendung von Gleitkommaoperationen entwickelt (ganzzahlige Operationen sind schneller). Es ist historisch sehr interessant, aber keine sehr gute Lösung für ein Spiel (insbesondere, weil Sie keine Geschwindigkeit angeben können).

Verwenden Sie bei einer 2D-Bewegung immer Vektoren. Dies wird alles für Sie tun. Manchmal ist Algebra einfach wunderbar.

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

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

Es wird sicher eine vector2D-Klasse für Ihre Zielsprache geben.

Notabene
quelle
Das hat perfekt funktioniert. Normalisieren war die Funktion, die ich brauchte. Vielen Dank.
user4761
9

Berechnen Sie jeden Frame? Ihr Code setzt entweder x_speed oder y_speed auf eine Zufallszahl und die andere auf Null (oder die Standardeinstellung). Angenommen, der Feind ist bei 0, 0 und der Spieler bei 20, 10. Dies sieht so aus, als würde x_speed in jedem Frame auf eine Zufallszahl gesetzt und der Feind nach rechts bewegt, bis er bei 10, 0 ist. Dann bewegt sich der Feind entweder x oder y für jedes Bild, so dass es den Anschein hat, als würde er sich in einem Winkel von 45 Grad bis zu 10, 10 bewegen.

Die Vektorerklärung von Notabene ist richtig, aber so funktioniert es. Der Vec2d hat eine x- und eine y-Komponente. Im obigen Beispiel erhalten Sie mit playerPos - feindPos einen Vektor von (20, 10). normalize () ändert den Vektor so, dass die Länge 1 beträgt. Derzeit beträgt die Länge sqrt (20 * 20 + 10 * 10). Das ist ungefähr 22.36068. Beim Normalisieren werden sowohl X als auch Y durch diese Zahl geteilt, sodass Sie ungefähr (0,89443, 0,44721) für die Richtung erhalten. Dies ist ein Vektor, der vom Feind zum Spieler mit einer Länge von 1 zeigt. Das Multiplizieren mit Ihrer zufälligen Geschwindigkeit macht das, was Sie wollen.

Ich würde jedoch nicht für jeden Frame eine neue Zufallsgeschwindigkeit berechnen. Sie möchten die zufällige Geschwindigkeit wahrscheinlich nur einmal einstellen oder eine Anfangsgeschwindigkeit und eine Zielgeschwindigkeit haben, die Sie jedem Bild näher kommen. Es macht für Ihren Feind keinen Sinn, zunächst 100 Meilen pro Stunde, dann 50 Meilen pro Stunde für einen Frame und 200 Meilen pro Stunde für den nächsten zu fahren.

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;
Jason Goemaat
quelle
Schöne Erklärungen und Ergänzungen Jason, danke. Ich mag deine Beschleunigungsfunktion
Notabene
random () in diesem Bereich war ein Tippfehler. Ihre Erklärung und Ihr Code mit dem, was notabene geschrieben hat, helfen mir, das Spiel zum Laufen zu bringen. Vielen Dank.
user4761