5

我正在使用 SpriteKit 编写一个涉及许多标记球的 iOS 游戏。我通过构建具有 2 个孩子的父 SKSpriteNode 来构建这些“rollingBalls”:

a) 一个 SKShapeNode(实际的圆形)

b) 和一个 SKLabelNode(标签)

球将在整个屏幕上移动,在二维中与彼此和其他对象交互,并且完全依赖于预期的物理特性(想想台球)。但是,如果可能的话,我希望标签不与父级一起旋转,以便它始终保持易于阅读。

最简单的方法是什么?

标签不应该是容器的子项吗?有没有其他方法可以将它固定在 ballShape 上?或者我可以在标签上设置一些属性等?

这是我现在得到的:

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;
4

4 回答 4

6

在此处输入图像描述

将所有标签放在一个容器中,将标签添加到关联节点的 userData,然后更新标签位置。

// 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;
        }
    }
}

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

于 2014-04-10T21:41:07.497 回答
5

这似乎有效

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

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

    }];
}
于 2013-10-16T21:54:40.207 回答
1

一种潜在的、超级简单的解决方案:

container.physicsBody.allowsRotation = NO

但这当然会阻止整个精灵旋转。

于 2013-10-16T21:36:13.417 回答
0

尽管其他解决方案也能正常工作,但我发现在使用物理模拟移动它们时,两个节点之间的间隙很小。

您可以使用 2 个物理实体并在它们之间添加一个销关节,这样它们将同时更新。我的 SKNode 子类的示例代码(注意:您需要将节点添加到场景/节点才能添加关节):

SKSpriteNode *overlay = [SKSpriteNode spriteNodeWithImageNamed:@"overlay"];
overlay.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:10.0];
overlay.allowsRotation = NO;
[self addChild:overlay];

self.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:26.0];

SKPhysicsJointPin *pinJoint = [SKPhysicsJointPin jointWithBodyA:overlay.physicsBody bodyB:self.physicsBody anchor:self.position];
[self.scene.physicsWorld addJoint:pinJoint];
于 2015-07-11T18:31:38.527 回答