Movimiento enemigo en línea recta al jugador en el juego de persecución

10

Estoy creando un juego donde los enemigos aparecen aleatoriamente en un mapa y luego se mueven hacia el jugador cada cuadro a una velocidad aleatoria. El mapa no tiene obstáculos, por lo que los enemigos siempre deben moverse en línea recta. Escribí la función de movimiento varias veces, pero no importa lo que los enemigos siempre golpeen 0, 45, 90, 135, 180, 225, 270, 315 ángulos, pero nunca una línea recta. Aquí hay un ejemplo del código:

    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;

Este es mi primer intento de programación de juegos. Supongo que debería usar un algoritmo como Bresenham's Line ( http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm ) pero mis intentos de implementar tienen el mismo problema. ¿Cómo hago para que los enemigos se muevan en línea recta?

usuario4761
fuente

Respuestas:

17

El algoritmo de línea de Bresenham se desarrolló para dibujar líneas rápidamente sin utilizar operaciones de punto flotante (las operaciones de enteros son más rápidas). Históricamente es una solución muy interesante pero no muy buena para un juego (especialmente porque no se puede especificar la velocidad).

Al hacer un movimiento 2D, use siempre vectores. Esto hará todo por ti. A veces el álgebra es simplemente maravilloso.

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

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

Seguramente habrá alguna clase de vector2D para su idioma de destino.

Notabene
fuente
Eso funcionó perfectamente. Normalizar era la función que necesitaba. Gracias.
user4761
9

¿Estás calculando cada cuadro? Su código establece x_speed o y_speed en un número aleatorio y el otro en cero (o el valor predeterminado). Digamos que el enemigo está en 0, 0 y el jugador está en 20, 10. Parece que establecerá x_speed en algún número aleatorio en cada cuadro y moverá al enemigo a la derecha hasta que esté en 10, 0. Entonces el enemigo se moverá x o y cada cuadro, por lo que parecerá que se mueve en un ángulo de 45 grados hasta 10, 10.

La explicación vectorial de Notabene es correcta, pero así es como funciona. El Vec2d tendrá un componente x e y. En el ejemplo anterior, playerPos - enemyPos te dará un vector de (20, 10). normalize () cambia el vector para que la longitud sea 1. Actualmente la longitud es sqrt (20 * 20 + 10 * 10). Eso es alrededor de 22.36068. normalizar divide tanto X como Y por este número, lo que le da aproximadamente (0.89443, 0.44721) para la dirección, que es un vector que apunta desde el enemigo al jugador con una longitud de 1. Multiplicar esto por tu velocidad aleatoria hace lo que quieres.

Sin embargo, no calcularía una nueva velocidad aleatoria en cada cuadro. Probablemente solo desee establecer la velocidad aleatoria una vez, o tener una velocidad inicial y una velocidad objetivo que se acerque a cada cuadro. No tiene sentido que tu enemigo vaya inicialmente a 100 mph, luego 50 mph para un cuadro y 200 mph para el siguiente.

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
fuente
Buenas explicaciones y adiciones Jason, gracias. Me gusta la función de aceleración tuya
Notabene
random () en ese ámbito era un error tipográfico. Tu explicación y código con lo que escribió notabene me ayudan a que el juego funcione. Gracias.
user4761