Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I have objects in my game that move faster at 45 degrees then at 90 degrees.

Each object has

  • Point (x,y) position
  • Vector2D (x,y) direction
  • Int speed

And what I do during a update is that new position is calculated as:

position.x += direction.x * speed
position.y += direction.y * speed

How do I correct this? I want it to move with the same speed at any angle.

share|improve this question
8  
Normalize your direction vector before use; problem solved. –  Daniel Jan 25 '12 at 8:49
1  
Had to google normalizing :) found this usefull site fundza.com/vectors/normalize/index.html –  Jason94 Jan 25 '12 at 9:04
    
And if you are using user input to control this object, be aware of locking to the 12,3,6,9 directions as explained here for XNA devs: xona.com/2010/05/03.html. It may be something you want (such as in an RPG game) or not (such as in a Geometry Wars style game). –  Xonatron Jan 25 '12 at 14:58
    
in the old game Descent, this was a feature. –  32bitkid Jan 25 '12 at 18:46
    
@32bitkid Yes, see also Doom straferunning –  bobobobo Apr 6 '13 at 22:42

4 Answers 4

up vote 53 down vote accepted

This can be explained with the Pythagorean Theorem, which is the following formula:

a² + b² = c²

In your case, when moving right, you're using (x:1, y:0) which gives us

c² = 1 + 0 = 1
c = sqrt(1) = 1.00

When moving up and right, you're using (x:1, y:1) which gives us

c² = 1 + 1 = 2
c = sqrt(2) = 1.41

So as you can see, the length diagonally is longer than the length on the cardinal axes.

As others have mentioned, you should simply normalize your direction vector. If you use XNA, it's done like this:

var normalizedDirection = direction;
normalizedDirection.Normalize();
position += normalizedDirection * speed
share|improve this answer
    
I'm giving you +1 for your help in my question :) –  Martin. Jan 26 '12 at 11:52

Normalize your direction vector before use.

As explained by MindWorX, this can be simply understood, if your worried about your direction vectors possibly giving you grief, make sure they are unit vectors (magnitude/length of 1).

Length(Vector2(1, 1)) == 1.4142135623730951 // first hint of grief
Length(Vector2(1, 0)) == 1

Vector2(1, 1) * 2 == Vector2(2, 2)
Vector2(1, 0) * 2 == Vector2(2, 0)

Length(Vector2(2, 2)) = 2.8284271247461903 // second hint
Length(Vector2(2, 0)) = 2

If normalized:

normal(Vector2(1, 1)) == Vector2(0.707107, 0.707107)
Length(Vector2(0.707107, 0.707107)) == 1 // perfect
share|improve this answer
14  
Not a helpful answer. If the questioner knew what "normalize your direction vector" meant, he would not have asked the question. –  Kristopher Johnson Jan 25 '12 at 13:14
    
@KristopherJohnson it was not clear the questioner did not know how to normalize a vector. Albeit the questioner seems resourceful enough that it did not matter anyway. –  Daniel Jan 25 '12 at 17:00
2  
@KristopherJohnson: if the questioner didn't know what "normalize your direction vector" means, he just need to type that to google, append the name of his language, and get a code with explanations. –  Lie Ryan Jan 26 '12 at 6:25

How are you calculating your direction? If 45 degrees is (1,1), then it's certainly going to be faster than 90 degrees (1,0).

I suggest you use something like this:

direction.x = Math.Cos(angleInRadians);
direction.y = Math.Sin(angleInRadians);

To get the angle in radians, you'll have to multiply your degrees with PI / 180 or even better, use MathHelper. Eg.

angleInRadians = 45.0 * Math.PI / 180.0; // first method
angleInRadians = MathHelper.ToRadians(45f); //second method
share|improve this answer
    
+1 For the geometry. –  C. Ross Jan 25 '12 at 14:55

Jason,

Rather than having three object attributes,

  • Point (x,y) position
  • Vector2D (x,y) direction
  • Int speed

it is often much easier to combine the direction and speed into a velocity vector. Then you have only two attributes,

  • Point (x,y) position
  • Vector2D (x,y) velocity

Updating position

When you need to update the object's position, it's as simple as:

position.x += velocity.x * Δt;
position.y += velocity.y * Δt;

where Δt is your time delta — or time difference — or time step.

Updating position and velocity

It is also very easy this way to handle acceleration (such as from gravity). If you have an acceleration vector, you can update the velocity and position together like this:

position.x += (velocity.x * Δt) + (0.5 * acceleration.x * Δt * Δt);
position.y += (velocity.y * Δt) + (0.5 * acceleration.y * Δt * Δt);

velocity.x += acceleration.x * Δt;
velocity.y += acceleration.y * Δt;

(This is basically the s = vt + ½at² formula from Physics 101.)

Applying a speed

If you want to apply a given speed in some normalized direction, you can set the velocity like this:

velocity.x = normalizedDirection.x * speed;
velocity.y = normalizedDirection.y * speed;

Deriving a speed

And if you need to do the reverse — deriving the speed and direction from a given velocity vector — you can simply use the Pythagorean theorem or the .Length() method:

speed = velocity.Length();

And once the speed is known, the normalized direction can be calculated by dividing the velocity by the speed (being careful to avoid dividing by zero):

if (speed != 0) {
    normalizedDirection.x = velocity.x / speed;
    normalizedDirection.y = velocity.y / speed;
} else {
    normalizedDirection.x = 0;
    normalizedDirection.y = 0;
}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.