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

时间:2014-01-20 07:43:10

标签: ios physics sprite-kit

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

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

我试图用重力归档这个,但精灵套件中的重力仅适用于垂直的X和Y轴,而不是Z轴。我还试图通过在beginContact上使用小物理体切换重力值来使用水平重力,具体取决于茶杯中当前的球位置。但有些联系人被删除,结果很远,看起来很现实。

我想我需要在update:方法中解决这个问题,但我不知道要走哪条路。 任何建议都非常欢迎,我需要提一下,我不是数学方面的专家,请解释一下你要走的路。 : - )

2 个答案:

答案 0 :(得分:2)

由于在SpriteKit中没有内置支持这种行为,而不是试图破解现有功能以获得你想要的东西,你可能最好在x,y 2D世界中集成一些已发布的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)];

答案 1 :(得分:0)

遵循Joshd的好主意,我创建了一个NSArray,就像上面的评论中所解释的一样。希望这些片段能帮助其他人......

结果可以在youtube上找到: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;
   }

最后,我正在检查阵列中是否有一个有效的球与一个洞接触,以避免在每次更新期间进行检查。这是通过以下功能完成的,其中位置检查+/- 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;
}