user1879027
user1879027

Reputation:

Sprite Kit: Getting the absolute node position

How can I get the absolute position of the _childNode in this example:

I have a parent: _worldNode

I have a child: _childNode

I set the _childNode position to 10,10.

I rotate _worldNode 90 degrees.

Now, when I query the _childNode position I am given 10,10. Naturally this is no longer the case. Even doing [_childNode calculateAccumulatedFrame] gives me a CGRect at 10,10.

Any ideas how to return the correct position (-10,10)? Here's the code from my test (just put into init, all logs return 10,10).

    CGRect screenRect = [[UIScreen mainScreen] bounds];
    CGFloat screenWidth = screenRect.size.width;
    CGFloat screenHeight = screenRect.size.height;
    CGPoint screenCentre = CGPointMake(screenHeight/2.0,screenWidth/2.0);

    _worldNode = [SKNode node];
    _worldNode.position = screenCentre;
    [self addChild:_worldNode];


    _childNode = [[SKSpriteNode alloc] initWithColor:[UIColor redColor] size:CGSizeMake(10, 10)];
    _childNode.position = CGPointMake(10, 10);
    [_worldNode addChild:_childNode];

    NSLog(@"position of child pre rotation %f, %f", _childNode.position.x, _childNode.position.y);

    _worldNode.zRotation = 90;

    NSLog(@"position of child after rotation %f, %f", _childNode.position.x, _childNode.position.y);

    CGPoint position = _childNode.position;
    [_childNode convertPoint:position toNode:_worldNode];

    NSLog(@"position of child after conversion %f, %f", position.x, position.y);

    CGRect groupRect = [_childNode calculateAccumulatedFrame];

    CGPoint newPosition = CGPointMake(groupRect.origin.x + (groupRect.size.width / 2), groupRect.origin.y + (groupRect.size.height / 2));
    NSLog(@"position of child based on frame %f, %f",newPosition.x,newPosition.y);

Many thanks in advance, Ian

Upvotes: 1

Views: 4429

Answers (2)

ZeMoon
ZeMoon

Reputation: 20274

There are a lot of mistakes in your code.

1-

_worldNode.position = screenCentre;  //This places the node at the SKScene centre

should be

_worldNode.position = CGPointZero; //This places the node at the origin.

The SKScene's default coordinate system has the origin at the lower left corner.

2-

_worldNode.zRotation = 90;

should be

_worldNode.zRotation = M_PI_2;

The zRotation is measured in radians, not degrees.

3-

Look at the two NSLogs in the code:

NSLog(@"position of child after rotation %f, %f", _childNode.position.x, _childNode.position.y); // - 1

CGPoint position = _childNode.position;
[_childNode convertPoint:position toNode:_worldNode]; //returns a CGPoint, where are you storing it?

NSLog(@"position of child after conversion %f, %f", position.x, position.y); // - 2

The position variable is not actually converted. The method returns another CGPoint which in turn will need to be logged.

However, this will return the wrong position as _childNode.position stores it's position relative to it's parent (i.e. _worldNode) and hence using convertPoint to _worldNode will convert (10,10) on the _childNode to _worldNode, making it (20,20).

Try using this line instead:

CGPoint position = [self convertPoint:_childNode.position fromNode:_worldNode];
NSLog (@"Position: %@", [NSValue valueWithCGPoint:position]);

This will give you the position w.r.t the Scene, which is what you were aiming at.

Upvotes: 1

Andrey Gordeev
Andrey Gordeev

Reputation: 32459

In short: rotation doesn't change node's position.

SKSpriteNode's position returns a position of an anchorPoint for that node.

When you rotate SKSpriteNode, it's rotating over its anchorPoint, so node's anchorPoint remains in the same position as it was before rotation. That's why you always get (10, 10)

Upvotes: 1

Related Questions