我正在使用SpriteKit编写一个涉及多个标记球的iOS游戏。我正在构建这些“滚动球”'通过构建一个包含2个子节点的父SKSpriteNode:
a)SKShapeNode(实际圆形)
b)和SKLabelNode(标签)
球将在整个屏幕上移动,彼此之间以及其他物体相互作用,在两个维度上,完全取决于预期的物理(想想台球)。但是,如果可能的话,我希望标签不与父母一起旋转,以便它始终易于阅读。
最简单的方法是什么?
标签不是容器的子容器吗?还有其他方法可以将它钉在球形状上吗?或者我可以在标签上设置一些属性等吗?
这是我现在所拥有的:
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;
答案 0 :(得分: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
答案 1 :(得分:5)
这似乎有效
-(void) didSimulatePhysics
{
[self enumerateChildNodesWithName:@"ball" usingBlock:^(SKNode *node, BOOL *stop) {
for (SKNode *n in node.children) {
n.zRotation = -node.zRotation;
}
}];
}
答案 2 :(得分:1)
一个潜在的,超级简单的解决方案:
container.physicsBody.allowsRotation = NO
但当然这会阻止整个精灵旋转。
答案 3 :(得分: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];