嗨我有一堆圆形SKSpriteNodes带有圆形物理身体。现在,当这些球滚下路径时,我希望这些SKSpritenodes图像中的一些即使在滚动时也能保持直立。所以想想一个向上的箭头。当球开始滚动时,箭头旋转成圆形。但是对于一些球来说,即使球滚动,箭头仍然指向上方。这是最好的方法吗?
修改
所以给出了答案但是从测试结果证明它不是正确的答案。不允许球旋转会影响它沿着路径滚动的方式。所以我想我想要的是旋转,但是图像总是向用户显示,就像它不旋转一样。感谢。
答案 0 :(得分:5)
这看起来像是 Superm SKConstraint
的工作。在物理模拟在每个帧上运行之后,对约束进行评估和应用,因此您可以将它们用于使节点指向某个方向的任务,而不管物理学对它做什么。为此,您需要zRotation
约束。
但是还有更多的东西。如果你在球上设置了零旋转约束:
// Swift
let constraint = SKConstraint.zRotation(SKRange(constantValue: 0))
ball.constraints = [constraint]
你会发现SpriteKit会因为约束而重置物理体对每一帧的变换,所以它只会像它的滚动一样。可能不是你想要的。 (为了更好地了解这里发生的事情,尝试在没有重力的世界中为矩形物理体添加零旋转约束,对其施加角度冲动,并观察它在视图中旋转showsPhysics
打开了。你会看到精灵和它的物理体失去同步并摇晃一下 - 可能是由于物理引擎和约束引擎对抗累积的舍入错误。)< / p>
相反,您可以在0x141E的答案中做一些事情,但是使用约束来减少代码(并且更有效地运行):
等等,这不起作用 - 我告诉箭头不要旋转,但它还在旋转?!请记住,子节点相对于其父节点定位(并旋转和缩放)。所以箭头不是相对于球旋转,而是球旋转。别担心,您仍然可以通过约束来解决这个问题:
现在约束将保持箭头到位,同时允许球旋转,但物理模拟需要它。
这里有一些测试代码来说明:
// Step 1: A rectangular spinner so we can see the rotation
// more easily than with a ball
let spinner = SKSpriteNode(color: SKColor.redColor(), size: CGSize(width: 300, height: 20))
spinner.position.x = scene.frame.midX
spinner.position.y = scene.frame.midY
spinner.physicsBody = SKPhysicsBody(rectangleOfSize: spinner.size)
scene.addChild(spinner)
spinner.physicsBody?.applyAngularImpulse(0.1) // wheeeeee
// Step 2: Make the arrow a child of the spinner
let arrow = SKSpriteNode(color: SKColor.greenColor(), size: CGSize(width: 20, height: 50))
spinner.addChild(arrow)
// Step 3: Constrain the arrow's rotation...
let constraint = SKConstraint.zRotation(SKRange(constantValue: 0))
arrow.constraints = [constraint]
// Step 4: ...relative to the scene, instead of to its parent
constraint.referenceNode = scene
答案 1 :(得分:1)
以下是使用物理主体和箭头创建球的两种方法:
以下是将上述内容添加到SpriteKit模拟时会发生的情况:
如果您希望箭头随球一起旋转,请选择选项1.如果您希望箭头保持固定,请选择选项2.如果选择选项2,则需要调整箭头的旋转以确保它指向上方。这是一个如何做到这一点的例子。
-(void)didMoveToView:(SKView *)view {
self.scaleMode = SKSceneScaleModeResizeFill;
/* Create an edge around the scene */
self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:view.frame];
// Show outline of all physics bodies
self.view.showsPhysics = YES;
CGFloat radius = 16;
SKNode *balls = [SKNode node];
balls.name = @"balls";
[self addChild:balls];
// Create 5 balls with stationary arrows
for (int i = 0;i<5;i++) {
// Create a shape node with a circular physics body. If you are targeting iOS 8,
// you have other options to create circular node. You can also create an SKSpriteNode
// with a texture
SKShapeNode *ball = [SKShapeNode node];
// Create a CGPath that is centered
ball.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(-radius,-radius,radius*2,radius*2)].CGPath;
ball.fillColor = [SKColor whiteColor];
ball.position = CGPointMake(100, 100+i*radius*2);
ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:radius];
[balls addChild:ball];
// Create an arrow node
CGSize size = CGSizeMake(2, radius*2);
SKSpriteNode *arrow = [SKSpriteNode spriteNodeWithColor:[SKColor blackColor] size:size];
arrow.name = @"arrow";
arrow.position = CGPointZero;
[ball addChild:arrow];
// Apply angular impulse to the ball so it spins when it hits the floor
[ball.physicsBody applyAngularImpulse:-1];
}
}
- (void) didSimulatePhysics
{
SKNode *balls = [self childNodeWithName:@"balls"];
for (SKNode *ball in balls.children) {
SKNode *arrow = [ball childNodeWithName:@"arrow"];
arrow.zRotation = -ball.zRotation;
}
}
答案 2 :(得分:0)
sprite.physicsBody.allowsRotation = NO;
allowRotation属性应该准确控制您的要求。