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.
Instead of explaining it to you, I'm going to point you to this wonderful Java applet:
http://catcode.com/trig/trig05.html
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:
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.
Instead of explaining it to you, I'm going to point you to this wonderful Java applet:
http://catcode.com/trig/trig05.html
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:
Code:
float angle;
float radians
void move_player()
{
NSPoint vector;
vector.x = new_world_dst.x  player.x;
vector.y = new_world_dst.y  player.y;
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 Xside to the X pos, and scale it to SPRITE_SPEED
position.y += sin(radians) * SPRITE_SPEED; // Add the Yside 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.
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.
Instead of explaining it to you, I'm going to point you to this wonderful Java applet:
http://catcode.com/trig/trig05.html
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:
Code:
float angle;
float radians
void move_player()
{
NSPoint vector;
vector.x = new_world_dst.x  player.x;
vector.y = new_world_dst.y  player.y;
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 Xside to the X pos, and scale it to SPRITE_SPEED
position.y += sin(radians) * SPRITE_SPEED; // Add the Yside 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.
DoG Wrote: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.
Just divide the components by the length of the vector:
Code:
vector.x = new_world_dst.x  player.x;
vector.y = new_world_dst.y  player.y;
float scale = SPRITE_SPEED/sqrt(vector.x^2 + vector.y^2)
position.x += vector.x*scale;
position.y += vector.y*scale;
Code:
vector.x = new_world_dst.x  player.x;
vector.y = new_world_dst.y  player.y;
float sqd = vector.x * vector.x + vector.y * vector.y;
if(sqd > 0.00001) {
float scale = SPRITE_SPEED/sqrt(sqd);
position.x += vector.x*scale;
position.y += vector.y*scale;
}
Code:
#define SPRITE_SPEED2 SPRITE_SPEED*SPRITE_SPEED
...
vector.x = new_world_dst.x  player.x;
vector.y = new_world_dst.y  player.y;
float sqd = vector.x * vector.x + vector.y * vector.y;
if(sqd > 0.00001f) {
float scale = SPRITE_SPEED2/sqd;
position.x += vector.x*scale;
position.y += vector.y*scale;
}
DoG Wrote: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.
What exactly is is that makes the latter mentioned method superior?
Code:
#define SPRITE_SPEED2 SPRITE_SPEED*SPRITE_SPEED
...
vector.x = new_world_dst.x  player.x;
vector.y = new_world_dst.y  player.y;
float sqd = vector.x * vector.x + vector.y * vector.y;
if(sqd > 0.00001f) {
float scale = SPRITE_SPEED2/sqd;
position.x += vector.x*vector.x*scale;
position.y += vector.y*vector.y*scale;
}
Sir, e^iÏ€ + 1 = 0, hence God exists; reply!
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 (performancewise) 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.
Oh yeah. Sin, cos, and atan2 are all very expensive (performancewise) 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.
edit: nvm  1:24am
Nevada Wrote:Oh yeah. Sin, cos, and atan2 are all very expensive (performancewise) 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?
Leroy Wrote:Correct me if I'm wrong but can't you just use sin and cos tables to eliminate the expense?
Yes, but at the cost of more rounding errors. Making a lookup table entry for every possible 32bit float is not an option.
Scott Lembcke  Howling Moon Software
Author of Chipmunk Physics  A fast and simple rigid body physics library in C.
Why are you trying to get around using a much easier, faster, and all round better method anyway?
On a modern processor, a sin/cos lookup table with any accuracy is almost certainly more expensive than just calculating the sin or cosine directly.
Possibly Related Threads...
Thread:  Author  Replies:  Views:  Last Post  
Formula for converting angle to vector?  komirad  2  10,365 
Jul 29, 2011 07:29 AM Last Post: ThemsAllTook 

Question Regarding the Reflect Angle of a Transition  iBaby  3  3,675 
Apr 27, 2010 03:15 PM Last Post: JustinFic 

ending location from angle and speed  Kazooless  5  4,684 
Apr 3, 2009 02:40 PM Last Post: Gillissie 

Angle between two points?  Graphic Ace  6  5,636 
Nov 8, 2008 12:11 PM Last Post: macnib 

calculating X and Y coordinates w/ an angle and distance  ferum  13  15,425 
Jun 25, 2008 10:53 PM Last Post: rosenth 