Mouvement ennemi en ligne droite vers le joueur dans le jeu de poursuite

10

Je crée un jeu où les ennemis apparaissent au hasard sur une carte puis se dirigent vers le joueur à chaque image à une vitesse aléatoire. La carte ne comporte aucun obstacle, les ennemis doivent donc toujours se déplacer en ligne droite. J'ai écrit la fonction de mouvement plusieurs fois mais peu importe ce que les ennemis frappent toujours les angles 0, 45, 90, 135, 180, 225, 270, 315 mais jamais une ligne droite. Voici un exemple du 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;

Ceci est ma première tentative de programmation de jeux. Je suppose que cela devrait utiliser un algorithme comme Bresenham's Line ( http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm ) mais mes tentatives d'implémentation ont le même problème. Comment faire bouger les ennemis en ligne droite?

user4761
la source

Réponses:

17

L'algorithme de ligne de Bresenham a été développé pour tracer rapidement des lignes sans utiliser d'opérations en virgule flottante (les opérations entières sont plus rapides). C'est une solution historique très intéressante mais pas très bonne pour un jeu (surtout parce que vous ne pouvez pas spécifier la vitesse).

Lorsque vous effectuez un mouvement 2D, utilisez toujours des vecteurs. Cela fera tout pour vous. Parfois, l'algèbre est tout simplement merveilleuse.

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

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

Il y aura certainement une classe vector2D pour votre langue cible.

Notabene
la source
Cela a parfaitement fonctionné. Normaliser était la fonction dont j'avais besoin. Merci.
user4761
9

Calculez-vous chaque image? Votre code définit x_speed ou y_speed sur un nombre aléatoire et l'autre sur zéro (ou par défaut). Disons que l'ennemi est à 0, 0 et que le joueur est à 20, 10. On dirait que cela fixera x_speed à un nombre aléatoire à chaque image et déplacera l'ennemi vers la droite jusqu'à ce qu'il soit à 10, 0. Ensuite, l'ennemi se déplacera soit x ou y chaque image, il semblera donc qu'il se déplace dans un angle de 45 degrés jusqu'à 10, 10.

L'explication vectorielle de Notabene est juste, mais voici comment cela fonctionne. Le Vec2d aura un composant x et y. Dans l'exemple ci-dessus, playerPos - ennemiPos vous donnera un vecteur de (20, 10). normalize () change le vecteur pour que la longueur soit 1. Actuellement, la longueur est sqrt (20 * 20 + 10 * 10). Cela représente environ 22,36068. normaliser divise à la fois X et Y par ce nombre, ce qui vous donne environ (0,89443, 0,44721) pour la direction, qui est un vecteur pointant de l'ennemi vers le joueur d'une longueur de 1. La multiplication par votre vitesse aléatoire fait ce que vous voulez.

Cependant, je ne calculerais pas une nouvelle vitesse aléatoire à chaque image. Vous voulez probablement juste définir la vitesse aléatoire une fois, ou avoir une vitesse initiale et une vitesse cible que vous vous rapprochez de chaque image. Cela n'a pas de sens que votre ennemi passe à 100 mi / h au départ, puis 50 mi / h pour une image et 200 mi / h pour la suivante.

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
la source
Belles explications et ajouts Jason, merci. J'aime votre fonction d'accélération
Notabene
random () dans cette portée était une faute de frappe. Votre explication et votre code avec ce que notabene a écrit m'aident à faire fonctionner le jeu. Merci.
user4761