# Incorrect sprite rotation with atan2() [duplicate]

I want to rotate a sprite so that it faces the mouse cursor/screen touch location. Currently I'm using the following method to compute the angle of rotation. The input position is the target point the sprite must face:

- (void) moveToPosition: (CGPoint)pos
{
moveTarget = pos;
const float targetX = (moveTarget.x - self.position.x);
const float targetY = (moveTarget.y - self.position.y);
const float angle   = atan2(targetX, targetY);
}


Then in the update method, which is called every frame, I do a linear interpolation between the target angle and the current, to ensure a smooth rotation:

- (void) update
{
const float currentAngle = self.rotation;
if (currentAngle != targetAngle)
{
const float newAngle = LerpF(currentAngle, targetAngle, [self getTurnSpeed] * Time.deltaTime);
self.rotation = newAngle;
}
}


This setup works OK, except when the target angle gets close to 180/-180 degrees. When it gets there the sprite just spins the whole way around in a very wacky manner. I've recorded a short video to illustrate.

Which would be the best way to handle these cases, when the angle wraps, and fix this weird spin effect caused by it?

## marked as duplicate by sam hocevar, bummzack, Anko, Seth Battin, Sean MiddleditchApr 7 '14 at 0:08

Let's speak radians. Your angle is clamped to a real range and from what I can see from your video I would say between −π/2 and 3π/2. Now you can also view angles in different ways, for example as points on a circle. This is clearly the intuitive way to see your problem : in your case the tip of your ship is the considered “angle point” on the circle. The advantage of viewing angles on a circle is that you have no discontinuities, i.e. that -π/2 and π/2 are actually the same point. This way your problem is obvious :
You're trying to interpolate from an angle a little on the right of the south angle—it therefore has a value somewhat larger than -π/2— and an angle a little on the left—it has a value a little less than 3π/2. Look at the circle on the right.
But you're using angle value on the real line (see the right line on the figure), which means that when you interpolate two angles (you current ship rotation and the target ship rotation), you go all way through 0 to connect a value close to -π/2 to a value close to 3π/2 (the gray part of the line in the image). You need to take into consideration the “jump” at 3π/2 = −π/2 of the angle representation to move along the correct path. The correct path is in the black arrow on the line in the image. It corresponds to the path made of the black arrow in the circle. The easiest way is to compute the distance between your start angle and your target angle on the real line (i.e. the absolute value of the difference between the two angles), and check if that distance is larger than π (i.e. larger than a half-circle). If it is, add 2π to the smallest angle. Then you can interpolate the angles and possibly remap the interpolated value to the correct range if required.
• I meant take the difference between you current ship rotation (start of the path) and the target ship rotation (end of the path), the take the absolute value of this difference. This is the standard way to compute distance on the real line, but somehow I did not want to bring the distance concept. Here is a simple pseudo-code : if( abs(currentAngle−targetAngle) >= π ) { min(currentAngle,targetAngle) += 2*π; } newAngle = LerpF(currentAngle,targetAngle,deltaT);. I reworded my answer to be a little clearer, hope it helps – Lærne Apr 3 '14 at 7:05