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?
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.
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.
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.
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;
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With