SpriteKit 节点旋转问题

Posted

技术标签:

【中文标题】SpriteKit 节点旋转问题【英文标题】:SpriteKit Node Rotational Issues 【发布时间】:2014-07-08 20:58:38 【问题描述】:

我正在尝试为 ios 开发一个涉及布娃娃状实体的基本游戏。基本上(如下所示),我有一个头、一个身体和一个右臂(这三个都是基本的精灵节点),它们通过针关节连接,模拟人体中的连接(大致)。

头部和身体完美地工作,当施加力时,身体完美地围绕头部旋转并最终在头部下方垂直休息(见图)。

手臂的底部通过销关节固定在身体上,应该围绕其底部旋转(有点像肩膀),并且设置为初始旋转 45 度,因此它看起来像物理之前的手臂引擎接管。

我的问题是:为什么手臂不会因为重力而处于垂直位置(如身体)?难道重力不应该导致手臂围绕其底部旋转,直到手臂的尖端直接位于手臂顶部(肩膀)的下方?此外,当对身体施加力时(如下面的示例代码所示),身体会完全按照应有的方式围绕颈部关节旋转,但手臂不会从当前方向移动(这是不可取的)。

如果不是这样,我该如何实现这个效果?

感谢您的宝贵时间,如果需要,我很乐意提供任何其他信息

物理模拟静止图片:

演示问题的相关代码:

//make the head node
SKSpriteNode *head = [SKSpriteNode spriteNodeWithImageNamed:@"head"];
head.size = CGSizeMake(20 * [CFLConstants universalWidthScaleFactor], 20 * [CFLConstants universalWidthScaleFactor]);
head.position = position;
head.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:head.size.width/2];
head.physicsBody.categoryBitMask = CFLPhysicsCategoriesHead;
head.physicsBody.collisionBitMask = 0;
head.physicsBody.dynamic = NO;
[self.ragdollLayer addChild:head];

//make the body node
SKSpriteNode *body = [SKSpriteNode spriteNodeWithImageNamed:@"body"];
body.size = CGSizeMake(head.size.width, head.size.width * 3);
body.position = CGPointMake(head.position.x, head.position.y - head.size.height/2 - body.size.height/2);
body.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:body.size];
body.physicsBody.categoryBitMask = CFLPhysicsCategoriesBody;
body.physicsBody.collisionBitMask = 0;
[self.ragdollLayer addChild:body];

//attach the head and the body (via a neck joint)
SKPhysicsJointPin *neckJoint = [SKPhysicsJointPin jointWithBodyA:head.physicsBody bodyB:body.physicsBody anchor:CGPointMake(head.position.x, head.position.y - head.size.height/2)];
[self.physicsWorld addJoint:neckJoint];

//make the right arm
SKSpriteNode *rightArm = [SKSpriteNode spriteNodeWithImageNamed:@"arm"];
rightArm.size = CGSizeMake(head.size.width/5, head.size.width/5 * 10);
rightArm.anchorPoint = CGPointZero;
CGPoint rightArmPosition = CGPointMake(body.position.x + body.size.width * 1/5, body.position.y + body.size.height * 1/5);
rightArm.position = rightArmPosition;
rightArm.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:rightArm.size];
rightArm.physicsBody.categoryBitMask = CFLPhysicsCategoriesRightArm;
rightArm.physicsBody.collisionBitMask = 0;
rightArm.zRotation = -M_PI_4;

//force which makes the arm problem even more noticeable
[body.physicsBody applyImpulse:CGVectorMake(100, 0)];
[self.ragdollLayer addChild:rightArm];

//make the joint which holds the right arm to the body, but should allow the arm to rotate about this point (and doesn't)
SKPhysicsJointPin *rightShoulderJoint = [SKPhysicsJointPin jointWithBodyA:body.physicsBody bodyB:rightArm.physicsBody anchor:rightArmPosition];
[self.physicsWorld addJoint:rightShoulderJoint];

【问题讨论】:

【参考方案1】:

根据我的经验,这是因为更改精灵上的锚点不会更改物理主体的锚点。虽然我发誓有时你不必这样做,所以也许这是操作顺序的事情。但无论如何,偏移物理主体的中心以考虑精灵锚点。比如:

spriteRightArm.anchorPoint = CGPointMake(0, 1);

spriteRightArm.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:spriteRightArm.size center:CGPointMake(spriteRightArm.size.width/2, -spriteRightArm.size.height/2)]; 

【讨论】:

然后,如果您只想测试手臂旋转与重力的关系,请在手臂的physicsBody 上使用applyTorque: 我遇到了类似的问题,但不幸的是这个解决方案对我不起作用:(。打开物理调试模式以便我可以看到物理体的轮廓,我确保矩形是在适当的地方。我在这里发布了我自己的问题,所以我不会在这里讨论。我已经使用 SpriteKit 一年多了,由于这样的问题,我现在对它感到非常失望影响核心游戏玩法。 系统工作正常,但这并不意味着它没有混乱。只要确保您了解锚点与添加到场景中的对象以及您正在使用的坐标系之间的关系,您就可能会找出问题所在。

以上是关于SpriteKit 节点旋转问题的主要内容,如果未能解决你的问题,请参考以下文章

Swift SpriteKit 在 x 轴上旋转节点

Swift SpriteKit - 防止精灵节点角旋转

Swift Spritekit 应用旋转脉冲

在 SpriteKit 中禁用 SKNode 的旋转

SpriteKit 以定义的角度停止旋转***

Xcode,SpriteKit:旋转整个场景,编辑数组内精灵的属性