Reputation: 2357
I'd like to rotate a spaceship around the z axis with the SKAction rotation method, depending on touch coordinates. After a touch the spaceship's nose should point to the touch point.
CGFloat rad = atan2f(touchPos.y - sprite.position.y, touchPos.x - sprite.position.x); // calc rad between vectors
SKAction *rotation = [SKAction rotateToAngle: rad duration: ??? shortestUnitArc:YES];
How can I adjust the duration so that the rotation speed is always the same (no matter how big the rotation angle is)?
The problem is that the radian occurs in the interval from -pi to pi (because of atan2). So the rotation depends on the quadrant touched and so does the speed.
Upvotes: 1
Views: 615
Reputation: 2357
I got it now:
I've translated the radian from [-Pi, Pi] to [0, 2Pi].
CGFloat prevRad = sprite.zRotation; // actual sprite rotation
if (prevRad < 0) prevRad = (M_PI)+((M_PI)+prevRad); // atan2 from 0 to 2PI
CGFloat rad = atan2f(touchLocation.y - sprite.position.y, touchLocation.x - sprite.position.x); // calc rad between vectors
if (rad < 0) rad = (M_PI)+((M_PI)+rad); // atan2 from 0 to 2PI
Then I used the difference between the old and the new radian divided by a factor:
CGFloat factor = 4.0f;
CGFloat diff = ABS(sprite.zRotation - rad);
CGFloat time = diff / factor;
SKAction *rotation = [SKAction rotateToAngle:rad duration: time shortestUnitArc:YES];
rotation.timingMode = SKActionTimingEaseInEaseOut;
[sprite runAction:rotation];
Upvotes: 2
Reputation: 20274
CGFloat factor = 5.0; //Adjust this to get your desired speed.
CGFloat rad = atan2f(touchPos.y - sprite.position.y, touchPos.x - sprite.position.x); // calc rad between vectors
CGFloat diff = ABS(node.zRotation - rad);
CGFloat time = diff / factor;
SKAction *rotation = [SKAction rotateToAngle: rad duration: time shortestUnitArc:YES];
Upvotes: 1