2014-01-20 5 views
0

Я пишу двумерную игру с шариком с комплектом спрайтов на iOS 7 и в настоящее время борюсь за одно физическое моделирование.Как имитировать гравитацию по оси z в 2D-игре с комплектом спрайтов

Чтобы объяснить ожидаемое поведение: если мяч упал в чашку чая, он будет крутиться, потерять скорость и, наконец, остановиться в центре чашки.

Я попытался архивировать это с помощью силы тяжести, но сила тяжести в наборе спрайтов применима только к вертикальной оси X и Y, а не по оси Z. Я также попытался использовать гравитацию уровня, переключив значения силы тяжести с небольшими физическими телами на beginContact в зависимости от текущего положения шара в чашке. Но некоторые контакты удаляются, и результат далеко, чтобы выглядеть реалистично.

Я думаю, что мне нужно решить это в обновлении: метод, но я понятия не имею, куда идти. Любые советы очень приветствуются, и я должен упомянуть, что я не специалист по математике, объясните свой путь. :-)

ответ

2

Поскольку в SpriteKit нет встроенной поддержки такого поведения, вместо того чтобы пытаться взломать существующие функции, чтобы получить то, что вы хотите, вам, вероятно, лучше интегрировать некоторые опубликованные 2D-формулы физики в 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)]; 
+0

благодаря Joshd, ваш пример делает именно то, что я ищу. Я немного поработал со следующими свойствами: ваше значение силы, масса/плотность и linearDamping, чтобы получить идеальный результат. – Projectizer

+0

Отлично. Хотелось бы получить зеленый чек, если бы он ответил на ваш вопрос! – joshd

+0

Поскольку у меня есть до 8 шаров и чашек, я добавил NSArray, чтобы держать уроки кубка каждый со ссылкой на класс шара, действующий в контакте с чашкой. In-up: я применяю силу для каждого шара, как показал ваш образец, ограничивая это каждые 10 мс. Это делает производительность неплохой, даже все шары падают в их чашки ... – Projectizer

0

следующий Joshd отличная идея, я создал NSArray с как объяснено в моем комментарии выше. Надеюсь, что это фрагменты действительно помогает некоторым другим ...

Результат можно найти на YouTube: http://youtu.be/Uephg94UH30 Извините за плохой частотой кадров Airplay, он отлично работает гладко на моем IPad

-update: функции делает работу, но только срабатывает, если _meditationIsActive. Этот bool установлен в -didBeginКонтакт:, когда любой шар соприкасается с отверстием.

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; 
} 
Смежные вопросы