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;
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
This seems to work
-(void) didSimulatePhysics
{
[self enumerateChildNodesWithName:@"ball" usingBlock:^(SKNode *node, BOOL *stop) {
for (SKNode *n in node.children) {
n.zRotation = -node.zRotation;
}
}];
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With