Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting the angle between Vector2

I want to move the star (coin in my code) to the exact top right corner of the screen when the car hit the star. Both star and road are moving downward at a constant speed during each update. The car does not move but appears to be moving upward because of the road moving downward. Although it can move to the left and right lane on user's command.

So I calculated the angle between the star and the top right corner of the screen using the following method

public double AngleBetween(Vector2 a, Vector2 b)
{
    return Math.Atan2(b.Y - a.Y, b.X - a.X);
}

In my Update method, the following calculate the velocity to move and send it to the top right corner of the screen

double angleBetween = coin.AngleBetween(coin.Position, new
   Vector2(currentGame.GraphicsDevice.Viewport.Bounds.Right, 0));              
collidedCoinVelocity = new Vector2((float)Math.Sin(angleBetween), 
   -(float)Math.Cos(angleBetween));

In my Draw method, I updated the coin.Position using

coin.Position += collidedCoinVelocity * 10 ;

The problem is the star (coin) is not sent to the top right corner as I wanted but it's somewhere in the middle of the right screen bound.

When the star is hit when it's on the right lane, the angle between it and the top right corner is always

1.2196048576751 radians = 69.878211 degree

When the star is on the left lane the angle is

0.952588487628243 radians = 54.5793 degree

Am I calculating the angle correctly, what am I missing? Perhaps I am forgetting to consider the downward movement of the star?

enter image description here

enter image description here

EDIT

I have updated the image to show the angle I am trying to calculate and edited my question to make it clearer.

EDIT 2

Added a second image to show where the star goes after being hit.

like image 931
PutraKg Avatar asked Sep 14 '13 03:09

PutraKg


People also ask

How do you find angle between two vectors?

The angle between two vectors a and b is found using the formula θ = cos-1 [ (a · b) / (|a| |b|) ]. If the two vectors are equal, then substitute b = a in this formula, then we get θ = cos-1 [ (a · a) / (|a| |a|) ] = cos-1 (|a|2/|a|2) = cos-11 = 0°. So the angle between two equal vectors is 0.

How do you find the angle between 3D vectors?

To calculate the angle between two vectors in a 3D space: Find the dot product of the vectors. Divide the dot product by the magnitude of the first vector. Divide the resultant by the magnitude of the second vector.


3 Answers

It seems you swapped sin and cos by accident, and there seems to be a random negative in there. Thus this line

collidedCoinVelocity = new Vector2((float)Math.Sin(angleBetween), 
   -(float)Math.Cos(angleBetween));

should probably be

collidedCoinVelocity = new Vector2((float)Math.Cos(angleBetween), 
   (float)Math.Sin(angleBetween));

Although you don't even need to calculate so many angles. To get a unit vector without angles just use

double dx = b.X - a.X;
double dy = b.Y - a.Y;
double mag = Math.Sqrt(dx * dx + dy * dy);
collidedCoinVelocity = new Vector2(dx, dy) / mag;
like image 108
Zong Avatar answered Sep 20 '22 10:09

Zong


Erhm... Just FYI; converting from cartesian coordinates to using angle, and then back to cartesian makes no sense here.

Just derive your final velocity like this:

Vector2 direction = new Vector2(currentGame.GraphicsDevice.Viewport.Bounds.Right, 0) - coin.Position;
direction.Normalize();

Velocity = direction * 10;
Position += Velocity;

Also; NEVER update position in Draw. Draw is for Drawing, not updating. Updating stays in Update!

Also 2; You should generalize your code. all moving objects should inherit the same base that includes things like Velocity, Position and Acceleration, and the code to handle these. That way, you only have to change your logic to manipulate Velocity and/or Acceleration to make stuff move.

MovingObject.Update:

Velocity += Acceleration * deltaTime;
Positioin += Velocity * deltaTime;

(deltaTime = time in seconds since last frame, or (float)gameTime.ElapsedGameTime.TotalSeconds)

Then you just use base.Update() at the end of your subClasses update, and position and speed will work :) as long as you set the correct values.

like image 23
Stig-Rune Skansgård Avatar answered Sep 19 '22 10:09

Stig-Rune Skansgård


I think you should do:

public double AngleBetween(Vector2 a, Vector2 b)
{
    return Math.Atan2(-(b.Y - a.Y), b.X - a.X);
}

Considering the reversed Y axis you need to negate Y components.

Then, as Zong Zheng Li wrote, you've swaped Sin and Cos:

collidedCoinVelocity = new Vector2((float)Math.Cos(angleBetween), 
   -(float)Math.Sin(angleBetween));

but you still need to negate the Vector2.Y component, due to the reversed Y axis.

like image 43
pinckerman Avatar answered Sep 18 '22 10:09

pinckerman