Below is a section of my code which handles a player's sprite rotating towards an angle after a user touches the screen:
touchState = TouchPanel.GetState();
Vector2 touchPosition;
if (touchState.Count > 0)
{
touchPosition = new Vector2(touchState[0].Position.X, touchState[0].Position.Y);
targetPosition = Math.Atan2(player.Position.X - touchPosition.X, player.Position.Y - touchPosition.Y);
if (angle_radians < targetPosition)
{
angle_radians += 2 * fps;
}
if(angle_radians > targetPosition)
{
angle_radians -= 2 * fps;
}
player.Angle = angle_radians * -1;
}
The problem I'm having is that when the angle goes past a certain point (I believe 3.15 radians?), the logic no longer functions correctly and the sprite reverses direction in a 360 circle until it meets the target position again.
I know there is something I'm missing from this logic, and I can see the problem, but I'm not sure how to approach handling it.
How would I prevent the sprite from reversing direction?
Thanks
EDIT: I tried the solution below but I only receive a positive number from 0-6 for angle_distance, what have I done wrong?
if (touchState.Count > 0)
{
touchPosition = new Vector2(touchState[0].Position.X, touchState[0].Position.Y);
targetPosition = Math.Atan2(player.Position.X - touchPosition.X, player.Position.Y - touchPosition.Y);
angle_distance = targetPosition - angle_radians + Math.PI;
angle_distance = angle_distance - Math.Floor(angle_distance / 2 / Math.PI) * 2 * Math.PI;
if (angle_distance < 0)
{
angle_radians -= 2 * fps;
}
if (angle_distance > 0)
{
angle_radians += 2 * fps;
}
player.Angle = angle_radians * -1;
}
EDIT: I now realise my mistake, correct solution is below
if (touchState.Count > 0)
{
touchPosition = new Vector2(touchState[0].Position.X, touchState[0].Position.Y);
targetPosition = Math.Atan2(player.Position.X - touchPosition.X, player.Position.Y - touchPosition.Y);
angle_distance = targetPosition - angle_radians + Math.PI;
angle_distance = angle_distance - Math.Floor(angle_distance / 2 / Math.PI) * 2 * Math.PI;
if (angle_distance < Math.PI)
{
angle_radians -= 2 * fps;
}
if (angle_distance > Math.PI)
{
angle_radians += 2 * fps;
}
player.Angle = angle_radians * -1;
}
Answer
First, find the signed distance between the two angles:
dist = targetAngle - currentAngle + pi
dist = dist - floor(dist / 2 / pi) * 2 * pi - pi
If it's negative, then subtract from the current angle to reach the other angle in the shortest time, if it's positive, then add to it.
No comments:
Post a Comment