如何用Sprite Kit在2D游戏中模拟Z轴的重力

我正在用iOS 7上的Sprite工具包编写2D球赛,目前正在努力进行一次物理模拟。

为了解释预期的行为:如果一个球落入一个茶杯,它会绕圈,放松速度,最后静止在杯子的中心。

我试着用重力来归档,但是精灵套件中的重力只适用于垂直的X轴和Y轴,而不是Z轴。 我也尝试通过在开始接触时根据茶杯中的当前球位置切换重力值与小物理体来使用水平重力。 但是一些联系人被丢弃,结果很遥远,看起来很现实。

我想我需要在更新方法中解决这个问题,但是我不知道要走哪条路。 任何build议非常欢迎,我需要提及的是,我不是math专家,请解释你的路要走。 🙂

由于在SpriteKit中没有内置的对这种行为的支持,而不是试图破解现有的函数来获得你想要的东西,所以你可能最好在你的x,y二维世界中集成一些发布的2D物理公式。 我会认为像模拟磁性或寻的行为可能是正确的。

一个简单的例子就像(在场景的-update:方法中):

CGFloat strength = 0.5; //(some scaling value) CGPoint ballLocation = ball.position; CGPoint cupLocation = cup.position; [ball.physicsBody applyForce:CGVectorMake((cupLocation.x - ballLocation.x) * strength, (cupLocation.y - ballLocation.y) * strength)]; 

遵循Joshd的主意,我创build了一个NSArray,就像我上面评论中所解释的那样。 希望这个片段确实帮助其他人…

结果可以在YouTube上find:http: //youtu.be/Uephg94UH30对不起的Airplay帧速率,它运行在我的iPad上完美的光滑

-update:函数完成工作,但只有在_meditationIsActive时才会触发。 这个布尔设置在-didBeginContact:当任何球接触到一个洞。

  if (_lastCheck > 0.005) { if (_meditationIsActive) { CGFloat strength = 0.1; //(some scaling value) CGPoint ballLocation; CGPoint holeLocation; for (MeditationHole * holeObj in _meditationHoles) { if (holeObj.connectedMeditationBall != nil) { ballLocation = holeObj.connectedMeditationBall.position; holeLocation = holeObj.position; [holeObj.connectedMeditationBall.physicsBody applyForce:CGVectorMake( (holeLocation.x - ballLocation.x) * strength, (holeLocation.y - ballLocation.y) * strength)]; } } _meditationIsActive = [self doesMeditationApplies]; } _lastCheck = 0; } 

最后,我要检查是否有一个有效的球与arrays接触,以避免在每次更新时检查。 这是通过以下function完成的:位置检查+/- 48检测接近球洞的球,+/- 1球静止

 - (bool)doesMeditationApplies { bool isInArea = NO; int perfectMatchCount = 0; for (MeditationHole * holeObj in _meditationHoles) { if (holeObj) { if (holeObj.connectedMeditationBall != nil) { MeditationBall * ballObj = holeObj.connectedMeditationBall; if ((ballObj.position.x >= holeObj.position.x - 48) && (ballObj.position.x <= holeObj.position.x + 48) && (ballObj.position.y >= holeObj.position.y - 48) && (ballObj.position.y <= holeObj.position.y + 48)) { isInArea = YES; } else { holeObj.connectedMeditationBall = nil; } if ((ballObj.position.x >= holeObj.position.x - 1) && (ballObj.position.x <= holeObj.position.x + 1) && (ballObj.position.y >= holeObj.position.y - 1) && (ballObj.position.y <= holeObj.position.y + 1)) { perfectMatchCount++; isInArea = YES; } } } } if (perfectMatchCount == _oxydStonesMax) { if (_sound) { self.pauseMusicPlaybackBlock(YES); NSLog(@"PlaySound Meditation"); [OxydScene PlaySystemSound:@"Win2"]; } isInArea = NO; [self showPauseScreenWithWin:YES andPauseOnly:NO]; } return isInArea; }