SpriteKit侧滚动不更新physicsWorld
按照这里的例子(目标C除外)和标准的苹果文档,我发现当myWorld
更新它的位置时, physicsWorld
不会更新它的位置。 我打开我的skView showsPhysics来validation这一点。 看这些截图。
任何议案之前: 一点点动议之后 走得更远一点 就在联系之前
这是我的myWorld
中心代码。 大部分的长度是由于我在处理边缘限制时非常冗长。
- (void)centerOnNode:(SKNode *)monkeyNode { CGPoint monkeyPosition = monkeyNode.position; // Check if monkey died if (monkeyPosition.y < myWorld.frame.origin.y - sceneHeight/2) { [self monkeyDied]; } // Check if monkey won if (monkeyPosition.x > skyFarRightSide.x) { [self monkeyWon:monkeyNode]; } // Define limits CGFloat scrollTopLimit = skyFarTopSide.y - sceneHeight/2; CGFloat scrollBottomLimit = 0; CGFloat scrollLeftLimit = 0; CGFloat scrollRightLimit = skyFarRightSide.x - sceneWidth/2; // Normal (no limits hit) scrolling if (monkeyPosition.x > scrollLeftLimit && monkeyPosition.x < scrollRightLimit && monkeyPosition.y > scrollBottomLimit && monkeyPosition.y < scrollTopLimit) { [myWorld setPosition:CGPointMake(-monkeyPosition.x, -monkeyPosition.y)]; } // At far left scrolling if (monkeyPosition.x < scrollLeftLimit) { // No y limits hit if (monkeyPosition.y > scrollBottomLimit && monkeyPosition.y < scrollTopLimit) { [myWorld setPosition:CGPointMake(0, -monkeyPosition.y)]; } // Bottom limit hit if (monkeyPosition.y < scrollBottomLimit) { [myWorld setPosition:CGPointMake(0, 0)]; } // Top limit hit if (monkeyPosition.y > scrollTopLimit) { [myWorld setPosition:CGPointMake(0, -scrollTopLimit)]; } } // At far right scrolling if (monkeyPosition.x > scrollRightLimit) { // No y limits hit if (monkeyPosition.y > scrollBottomLimit && monkeyPosition.y < scrollTopLimit) { [myWorld setPosition:CGPointMake(-scrollRightLimit, -monkeyPosition.y)]; } // Bottom limit hit if (monkeyPosition.y < scrollBottomLimit) { [myWorld setPosition:CGPointMake(-scrollRightLimit, 0)]; } // Top limit hit if (monkeyPosition.y > scrollTopLimit) { [myWorld setPosition:CGPointMake(-scrollRightLimit, -scrollTopLimit)]; } } // At far bottom scrolling if (monkeyPosition.y < scrollBottomLimit) { // No x limits hit if (monkeyPosition.x > scrollLeftLimit && monkeyPosition.x < scrollRightLimit) { [myWorld setPosition:CGPointMake(-monkeyPosition.x, 0)]; } // Left limit hit if (monkeyPosition.x < scrollLeftLimit) { [myWorld setPosition:CGPointMake(0, 0)]; } // Right limit hit if (monkeyPosition.x > scrollRightLimit) { [myWorld setPosition:CGPointMake(-scrollRightLimit, 0)]; } } // At far top scrolling if (monkeyPosition.y > scrollTopLimit) { // No x limits hit if (monkeyPosition.x > scrollLeftLimit && monkeyPosition.x < scrollRightLimit) { [myWorld setPosition:CGPointMake(-monkeyPosition.x, -scrollTopLimit)]; } // Left limit hit if (monkeyPosition.x < scrollLeftLimit) { [myWorld setPosition:CGPointMake(0, -scrollTopLimit)]; } // Right limit hit if (monkeyPosition.x > scrollRightLimit) { [myWorld setPosition:CGPointMake(-scrollRightLimit, -scrollTopLimit)]; } } }
有没有一个优雅的方式来解决这个问题? 到目前为止,我唯一的想法是在centerOnNode
中包含更多的代码,以重置myWorld
中每个physicsBody
的位置。
我注意到,一旦这只猴子接触到了,所有的物理机构都会回到正确的位置。 但是,一个关节anchorPoint
结束了错误的地方。
我在GameScene.m中添加了以下便捷方法。
-(CGPoint)convertSceneToFrameCoordinates:(CGPoint)scenePoint { CGFloat xDiff = myWorld.position.x - self.position.x; CGFloat yDiff = myWorld.position.y - self.position.y; return CGPointMake(scenePoint.x + self.frame.size.width/2 + xDiff, scenePoint.y + self.frame.size.height/2 + yDiff); }
我使用这种方法来添加关节。 它处理所有需要处理的坐标系转换,导致在这个问题中提出的问题。 例如,我添加关节的方式
CGPoint convertedRopePosition = [self convertSceneToFrameCoordinates:ropePhysicsBody.node.position]; SKPhysicsJointPin *jointPin = [SKPhysicsJointPin jointWithBodyA:monkeyPhysicsBody bodyB:ropePhysicsBody anchor:convertedRopePosition]; jointPin.upperAngleLimit = M_PI/4; jointPin.shouldEnableLimits = YES; [self.scene.physicsWorld addJoint:jointPin];
我不知道过去两年有什么变化,但是这里的其他答案已经不再适用了。 相反,现在我将绳索段的位置与其父母(完整的绳索)相结合。 所以我只是做
CGPoint convertedRopePosition = CGPointMake(ropePhysicsBody.node.parent.position.x + ropePhysicsBody.node.position.x, ropePhysicsBody.node.parent.position.y + ropePhysicsBody.node.position.y); SKPhysicsJointPin *jointPin = [SKPhysicsJointPin jointWithBodyA:monkeyPhysicsBody bodyB:ropePhysicsBody anchor:convertedRopePosition];
这是因为绳段被放置在绳索的全长下,所以它的位置是相对于完整的绳索而不是现场。