SpriteKit 侧滚动不会更新 physicsWorld
SpriteKit side scrolling doesn't update physicsWorld
根据示例 here(Objective C 除外)和标准 Apple 文档,我发现 physicsWorld
在 myWorld
更新时不会更新其位置它的位置。我在我的 skView 上打开 showsPhysics
来验证这一点。请参阅这些屏幕截图。
在任何动议之前:
稍微动一下后
走得更远一点
就在接触之前
这是我的居中代码 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];
我不知道过去 2 年发生了什么变化,但这里的其他答案不再有效。相反,现在我将绳索段位置与其父级(完整绳索)的位置结合起来。所以我只是
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];
这是必需的,因为绳段位于绳索的全长下方,因此它的位置是相对于整条绳索而不是场景。
根据示例 here(Objective C 除外)和标准 Apple 文档,我发现 physicsWorld
在 myWorld
更新时不会更新其位置它的位置。我在我的 skView 上打开 showsPhysics
来验证这一点。请参阅这些屏幕截图。
在任何动议之前:
这是我的居中代码 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];
我不知道过去 2 年发生了什么变化,但这里的其他答案不再有效。相反,现在我将绳索段位置与其父级(完整绳索)的位置结合起来。所以我只是
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];
这是必需的,因为绳段位于绳索的全长下方,因此它的位置是相对于整条绳索而不是场景。