10
\$\begingroup\$

I'm creating a game where the enemies spawn randomly on a map then move towards the player every frame at a random speed. The map has no obstacles so the enemies should always move in a straight line. I wrote the movement function a few times but no matter what the enemies always hit 0, 45, 90, 135, 180, 225, 270, 315 angles but never a straight line. Here is an example of the 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;

This is my first attempt at game programming. I guessing it's should use algorithm like Bresenham’s Line( http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm) but my attempts to implement have the same issue. How do I make enemies move in a straight line?

\$\endgroup\$

2 Answers 2

17
\$\begingroup\$

Bresenham's line algorithm was developed for fast drawing lines without using floating point operations (integer operations are faster). It is very interesting historicaly but not very good solution for a game (especialy because you cannot specify speed).

When doing a 2D movement use always vectors. This will do all the stuff for you. Sometimes is algebra just wonderful.

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

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

There will be some vector2D class for your target language for sure.

\$\endgroup\$
1
  • \$\begingroup\$ That worked perfectly. Normalize was the function I needed. Thanks. \$\endgroup\$
    – user4761
    Jan 21, 2011 at 0:24
9
\$\begingroup\$

Are you calculating every frame? Your code sets either x_speed or y_speed to a random number and the other to zero (or the default). Let's say the enemy is at 0, 0 and player is at 20, 10. This looks like it will set x_speed to some random number each frame and move the enemy to the right until he is at 10, 0. Then the enemy will move either x or y each frame so it will seem he moves in a 45 degree angle up to 10, 10.

Notabene's vector explanation is right but here's how it works. The Vec2d will have an x and y component. In the example above, playerPos - enemyPos will give you a vector of (20, 10). normalize() changes the vector so that the length is 1. Currently the length is sqrt(20 * 20 + 10 * 10). That is about 22.36068. normalize divides both X and Y by this number, giving you about (0.89443, 0.44721) for the direction, which is a vector pointing from the enemy to the player with a length of 1. Multiplying this by your random speed does what you want.

However I would not calculate a new random speed each frame. You probably just want to set the random speed once, or have an initial speed and a target speed that you get closer to each frame. It doesn't make sense for your enemy to go 100 mph initially, then 50 mph for one frame and 200 mph for the next.

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;
\$\endgroup\$
2
  • \$\begingroup\$ Nice explanations and additions Jason, thanks. I like yours acceleration function \$\endgroup\$
    – Notabene
    Jan 20, 2011 at 15:25
  • \$\begingroup\$ random() in that scope was a typo. Your explanation and code with what notabene wrote help me get the game working. Thanks. \$\endgroup\$
    – user4761
    Jan 21, 2011 at 0:27

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .