Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I prevent the child of an SKSpriteNode from rotating with its parent?

I'm using SpriteKit to write an iOS game that involves a number of labeled balls. I'm constructing these 'rollingBalls' by building a parent SKSpriteNode with 2 children:

a) an SKShapeNode (the actual circle shape)

b) and an SKLabelNode (the label)

The balls will be moving all over the screen, interacting with each other and other objects, in 2 dimensions, and entirely dependent on the expected physics (think billiards). But if at all possible I'd like the label to NOT rotate with the parent, so that it's remains easily readable at all times.

What's the easiest way to do this?

Should the label not be a child of the container? Is there some other way to peg it to the ballShape? Or is there some property I can set on the label, etc.?

Here's what I've got now:

double ballDiameter = 40;
UIBezierPath* ovalPath = [UIBezierPath bezierPathWithOvalInRect: 
                            CGRectMake(-ballDiameter / 2, -ballDiameter / 2, 
                                        ballDiameter, ballDiameter)];

SKSpriteNode *container = [[SKSpriteNode alloc]init];

container.name = @"rollingBall";

SKShapeNode *ballShape = [[SKShapeNode alloc] init];
ballShape.path = ovalPath.CGPath;

SKLabelNode *ballLabel = [SKLabelNode labelNodeWithFontNamed:@"Arial"];
ballLabel.text = @"some random string";
ballLabel.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeCenter;
ballLabel.verticalAlignmentMode = SKLabelVerticalAlignmentModeCenter;
ballLabel.position = CGPointMake(0,0);

[container addChild:ballShape];
[container addChild:ballLabel];

container.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:ballDiameter / 2];
container.physicsBody.usesPreciseCollisionDetection = YES;
like image 891
doublea Avatar asked Oct 16 '13 21:10

doublea


2 Answers

enter image description here

Put all of the labels in a single container, add the label to the associated node's userData, then update label positions.

// Add a container as a scene instance variable.
SKNode *labels;

- (void)addLabelContainer
{
    labels = [SKNode node];
    [self addChild:labels];
}

- (void)addLabelForNode:(SKNode*)node
{
    SKLabelNode *label = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];
    node.userData = [NSMutableDictionary dictionaryWithObject:label forKey:@"label"];
    label.text = node.name;
    label.fontSize = 5;
    label.zPosition = node.zPosition + 1;
    [labels addChild:label];
}

- (void)removeLabelForNode:(SKNode*)node
{
    [[node.userData objectForKey:@"label"] removeFromParent];
    [node.userData removeObjectForKey:@"label"];
}

- (void)update:(NSTimeInterval)currentTime
{
    for (SKNode *node in self.children) {
        SKNode *label = (SKLabelNode*)[node.userData objectForKey:@"label"];
        if (label) {
            label.position = node.position;
        }
    }
}

See https://github.com/pmark/MartianRover/blob/master/hiSpeed/hiSpeed/Scenes/LimboScene.m

like image 190
pmark Avatar answered Oct 08 '22 11:10

pmark


This seems to work

-(void) didSimulatePhysics
{
    [self enumerateChildNodesWithName:@"ball" usingBlock:^(SKNode *node, BOOL *stop) {

        for (SKNode *n in node.children) {
            n.zRotation = -node.zRotation;
        }

    }];
}
like image 44
DogCoffee Avatar answered Oct 08 '22 12:10

DogCoffee