Recently I encountered a very strange problem in my development, and finally it turned out that the cause is my incomplete understanding of sprite’s rotation. Hence I write this article to share my experience with you.
Denotation of Rotation
In cocos2d sprite, the rotation is denoted as degrees instead of radians. Yet they provide two very convenient conversion macros CC_DEGREES_TO_RADIANS and CC_RADIANS_TO_DEGREES.
The rotation denotation is illustrated by image below.
1. When rotation equals to 0, the sprite is facing the right east. That is to say, positive x direction 0 degree. And the negative x direction is 180o or –180o.
2. In cocos2d, the angle is clockwise calculated. So the angle α above is a negative angle, which is opposite to the value computed by atan functions. As a result, we have to multiple –1 to get the right angle for cocos2d use. For example, point P in above figure. The code below implement the rotation change.
1: CGPoint pos = [sprite position];
2: float angle = CC_RADIANS_TO_DEGREES(atan2f(p.x - pos.x, p.y - pos.y));
3: angle *= -1;
4: [sprite setRotation:angle];
Here comes the first trap. If we want to continuously change the rotation from an angle to another angle, at first thought, this is extremely easy. We just compute the delta angle and gradually let original angle approach the destination angle. However, the simple accumulation method is not work under some situations. For example, see below figure.
We want to rotate a sprite from angle to the desAngle. According to the cocos2d denotation. The angle is 1500, while the desAngle is –1500. Using the straightforward method mentioned above, we will get the delta angle, which is –300 degrees, and then we gradually decrease the angle to the desAngle. Obviously, sprite will rotate anti-clockwise, which, in this case, is stupid and not smooth. We want the sprite rotating follow the arrow’s direction. Hence, we need to handle these situations carefully. The concept of solution is like this, once we detect that the absolute value of delta angle is bigger than 1800, we have to handle it differently. See the solution below.
Here is another small but annoying trap. Since the 0 degree is directly facing the right, if your sprite is vertical, you need to adjust the angle carefully. See below figure.
For example, you want to rotate your sprite clockwise by α degrees. Then you use the method mentioned in the Denotation of Rotation part to get the rotation angle, however, what you get is not α. Through that way, what you get is β. It’s a little bit hard to think through, but always remember that the calculation of angle starts from the positive x direction! Hence, to solve this problem, we need to plus 90 when setting the real rotation. See the above right figure. What’s more, before using rotation that is get from [sprite rotation], to be consistent, we have to subtract 90 degrees.
Cocos2d rotation sometimes doesn’t fit into our intuition, thus we need to handle it more carefully. So far, there are two traps to remember when putting it into use. One is handling continuous rotation, and the other is vertical sprite’s rotation.
Hope this article helps!