0

I'm running a rotateBy action that's repeated forever for a node, and occasionally I want to get the node's current rotation. But zRotation always return 0. How can I get the correct zRotation for this node?

Edit: so finally what I'm doing is creating a custom rotation action instead of using Sprite Kit's default action. A lot more complicated and hard to extend but it does what I want and can be encapsulated in each node's own class.

AVAVT
  • 7,058
  • 2
  • 21
  • 44
  • How are you determining that the `zRotation` property is 0? It updates as expected when I implemented a simple `rotateBy` action. – 0x141E Jul 06 '15 at 23:24
  • Can I see your code snippet? – AVAVT Jul 07 '15 at 03:35
  • Did you resolve this issue? – 0x141E Jul 14 '15 at 21:23
  • I had to use an work around. What I found out is that during rotateBy if I have the sprite check its own zRotation (by calling `self.zRotation`) it will return 0, but if I get its zRotation from another object (`node.zRotation`) it would return the correct value. Furthermore the sprite's `setZRotation:` is not called at all before, during and after the action run. Anyway I just make a child sprite inside a node instead of using a sprite directly now. – AVAVT Jul 15 '15 at 03:05
  • `self` is the scene not the node you are rotating. That's why it's always zero. In my answer below, I am printing `sprite.zRotation` not `self.zRotation` – 0x141E Jul 15 '15 at 09:25
  • I mean calling self.zRotation in MyCustomSpriteNode.m ... – AVAVT Jul 16 '15 at 06:12

2 Answers2

3

I believe the reason why you are getting 0 is because you are using animation. The properties of nodes undergoing animation are not updated at each step in the simulation. You will need to manually rotate the node in the update method or create a physics body and set the angular velocity. Using real-time motion will allow you to constantly monitor the properties of you nodes at each step in the simulation.

You can see an example of simulating rotation using real-time motion (albeit more complex) in my answer here.

Community
  • 1
  • 1
Epic Byte
  • 33,840
  • 12
  • 45
  • 93
  • Hmm node.physicsBody.angularRotation seems to have the same problem with SKAction. Your real-time motion solution is what I'm doing too, but I still hope there's a cleaner, more object-oriented solution for this. – AVAVT Jul 06 '15 at 05:28
  • 1
    @AvAvt Welcome to the world of game development. Sometimes traditional OOP solutions in games don't work. This is because games often need to be real-time and very dynamic. Similarly, you will find composition design often more useful than inheritance as the former is much more flexible. Furthermore, you can use custom classes to abstract the real-time code to keep the code more clean. This prevents your update method from filling up with arbitrary lines of code. – Epic Byte Jul 06 '15 at 15:04
0

If you paste the following into a new project, you should see the zRotation property change over time. With an 180 degree/second rotational rate and 60 FPS, the zRotation changes by ~3 degrees per update.

@implementation GameScene {
    SKSpriteNode *sprite;
}

-(void)didMoveToView:(SKView *)view {        
    self.scaleMode = SKSceneScaleModeResizeFill;

    sprite = [SKSpriteNode spriteNodeWithImageNamed:@"Spaceship"];
    sprite.xScale = 0.5;
    sprite.yScale = 0.5;
    sprite.position = CGPointMake (CGRectGetMidX(view.frame),CGRectGetMidY(view.frame));

    SKAction *action = [SKAction rotateByAngle:M_PI duration:1];

    [sprite runAction:[SKAction repeatActionForever:action]];

    [self addChild:sprite];
}

-(void)didEvaluateActions {
    // Wrap at 360 degrees
    CGFloat angle = fmod(sprite.zRotation*180/M_PI, 360.0);
    NSLog(@"%g",angle);
}

@end
0x141E
  • 12,613
  • 2
  • 41
  • 54