2
\$\begingroup\$

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;
                }
\$\endgroup\$
  • \$\begingroup\$ It should reverse at exactly 0 or 2 * pi radians \$\endgroup\$ – Bálint Nov 7 '17 at 21:41
0
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ Thanks very much for your reply, please could you see my edit above for my response? \$\endgroup\$ – pytheron Nov 7 '17 at 22:57
  • \$\begingroup\$ @pytheron of course you get something between 0 and 6.28, it's in radians, it goes from 0 to 2pi \$\endgroup\$ – Bálint Nov 8 '17 at 6:49
  • \$\begingroup\$ Myself, I like the formula (toAngle - fromAngle + 900) % 360 - 180 if both angles are >= -360 (That's (toAngle - fromAngle + 5*pi) % (2*pi) - pi in radians). Or to insure against angles in any range, ((toAngle - fromAngle + 180) % 360 + 360) % 360 - 180 \$\endgroup\$ – DMGregory Nov 8 '17 at 11:56
  • \$\begingroup\$ @DMGregory Yeah, (x % 360 + 360) % 360 is the same as dist - floor(dist / 360) * 360 \$\endgroup\$ – Bálint Nov 8 '17 at 12:57
  • \$\begingroup\$ @Bálint thanks very much again for your reply - I now realise that you meant the angle distance should be > or < than pi, and the sprite rotates correctly \$\endgroup\$ – pytheron Nov 9 '17 at 1:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.