Convert vector to angle?

So why aren't you striving to get better, by doing it the right way? It's a little bit like learning to drive by constantly having someone drive the car to a hilltop, and then sit by the wheel as it rolls down the hill.

Play around with it for a while to get a feel for what the sine and cosine actually are. What you're doing in your application (with regards to moving the player at an angle, not the atan2f stuff) is that you take the angle and ask for the X and Y sides of the triangle. Think of it like this: you have your angle, and you want to move in the direction of it. That's the same as moving in the direction of the hypotenuse. (Regardless of which direction you want to move in, you can always stick a right triangle to that vector, where the short sides make up the X and Y directions.)

Now, here comes the trick: you want a hypotenuse with a length of exactly 1. Why? Well, because it's easy to scale. If you want to move by 30pixels/sec, you do in fact want to move 1 * 30 pixels/sec, right? Might seem trivial, but it will come in handy, since that also means that the X and Y speeds you want to move in are the X and Y sides of that triangle, times 30. What you're doing is:
1) constructing a right triangle
2) with a hypotenuse of 1
3) and then scaling that entire triangle up to the speed you want to move with

It's dead simple! To figure out the short sides of the triangle, you use sin(angle) and cos(angle), which gives you the lengths of the two short sides. Now, just scale those sides up.

Therefore, the complete (and very, very standard) code you'll get is the following:

angle = atan2(vector.y, vector.x); // The ONLY right way to get the angle
// Also, atan2 returns in radians already
position.x += cos(radians) * SPRITE_SPEED; // Add the X-side to the X pos, and scale it to SPRITE_SPEED
position.y += sin(radians) * SPRITE_SPEED; // Add the Y-side to the Y pos, and scale it to SPRITE_SPEED
}

I hope that clears things up for you. And a little morale of the story: whenever you don't understand code, it will bite you bad. If nothing else, you've skipped an opportunity for learning, which is a terrible thing to waste.

Things you are still doing wrong: converting to an angular coordinate system and back again when it could have been done faster.
And in the special case of new_world_dst == player you would probably want the position to remain the same.

Fenris Wrote:So why aren't you striving to get better, by doing it the right way? It's a little bit like learning to drive by constantly having someone drive the car to a hilltop, and then sit by the wheel as it rolls down the hill.

Play around with it for a while to get a feel for what the sine and cosine actually are. What you're doing in your application (with regards to moving the player at an angle, not the atan2f stuff) is that you take the angle and ask for the X and Y sides of the triangle. Think of it like this: you have your angle, and you want to move in the direction of it. That's the same as moving in the direction of the hypotenuse. (Regardless of which direction you want to move in, you can always stick a right triangle to that vector, where the short sides make up the X and Y directions.)

Now, here comes the trick: you want a hypotenuse with a length of exactly 1. Why? Well, because it's easy to scale. If you want to move by 30pixels/sec, you do in fact want to move 1 * 30 pixels/sec, right? Might seem trivial, but it will come in handy, since that also means that the X and Y speeds you want to move in are the X and Y sides of that triangle, times 30. What you're doing is:
1) constructing a right triangle
2) with a hypotenuse of 1
3) and then scaling that entire triangle up to the speed you want to move with

It's dead simple! To figure out the short sides of the triangle, you use sin(angle) and cos(angle), which gives you the lengths of the two short sides. Now, just scale those sides up.

Therefore, the complete (and very, very standard) code you'll get is the following:

angle = atan2(vector.y, vector.x); // The ONLY right way to get the angle
// Also, atan2 returns in radians already
position.x += cos(radians) * SPRITE_SPEED; // Add the X-side to the X pos, and scale it to SPRITE_SPEED
position.y += sin(radians) * SPRITE_SPEED; // Add the Y-side to the Y pos, and scale it to SPRITE_SPEED
}

I hope that clears things up for you. And a little morale of the story: whenever you don't understand code, it will bite you bad. If nothing else, you've skipped an opportunity for learning, which is a terrible thing to waste.

Actually atan2 returns the angle value in radians so you wouldn't do position.x += cos(radians) * SPRITE_SPEED you'd use position.x += cos(angle) * SPRITE_SPEED instead. And I was only kidding around earlier when about the inversion thing

Leroy Wrote:Actually atan2 returns the angle value in radians so you wouldn't do position.x += cos(radians) * SPRITE_SPEED you'd use position.x += cos(angle) * SPRITE_SPEED instead. And I was only kidding around earlier when about the inversion thing

Actually using atan2() for this is quite stupid

You can save yourself the whole ordeal and just use the normalized vector in the first place.

Whoa there. Why are we squaring everything? The square of a ratio is not identical to the ratio itself. I realize we're trying to avoid the overhead of the expensive sqrt call, but if you square the ratio, you'll have to take the square root anyway. Hog had it right...

Oh yeah. Sin, cos, and atan2 are all very expensive (performance-wise) function calls and are very prone to rounding errors. So if we can avoid all that with one call to sqrt, the routine should perform better.

Nevada Wrote:Oh yeah. Sin, cos, and atan2 are all very expensive (performance-wise) function calls and are very prone to rounding errors. So if we can avoid all that with one call to sqrt, the routine should perform better.

Correct me if I'm wrong but can't you just use sin and cos tables to eliminate the expense?