Cocos2D Реалистичная гравитация?

Я испробовал множество различных техник применения реалистичной функции гравитации в своей игре, но пока безуспешно. Я планирую предложить вознаграждение в 100 баллов тому, кто покажет мне или (поделится) некоторый код, применяющий гравитацию к CCSprite в Cocos2D.

То, что я сделал до сих пор, было просто уродливым или нереалистичным, и я спрашивал во многих разных местах о том, какой лучший подход, но я просто еще не нашел каких-либо хороших методов гравитации.

В любом случае, может ли кто-нибудь предложить несколько советов/идей или свой подход только к применению гравитации к CCSprite в Cocos2D без использования физического движка?

Спасибо!


person SimplyKiwi    schedule 14.07.2012    source источник


Ответы (2)


Эффективным подходом без явного использования какого-либо физического движка является ручное изменение скорости и положения вашего спрайта в цикле обновления. По сути, это интегрирование по Эйлеру.

// define your gravity value
#define GRAVITY -0.1

// define a velocity variable in the header of your Game class/CCSprite Subclass (neater)
float velocity_y;

-(void) update: (ccTime) dt
{
    // Step the y-velocity by your acceleration value (gravity value in this case)
    velocity_y += GRAVITY *dt; // drop the dt if you don't want to use it 

    // Step the position values and update the sprite position accordingly
    sprite.position.y += velocity_y* dt; // same here
}

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

Далее идет суть Эйлера. На каждом временном шаге:

  1. Увеличьте свою скорость на свое ускорение (которое является вашей гравитацией), умноженное на dt, чтобы найти новую скорость.
  2. Переместите свою позицию на новое вычисленное значение скорости, умноженное на dt, чтобы найти новую позицию.

Вы можете поэкспериментировать, работает ли использование дельта-времени для вашей игры или нет (см. отличный комментарий LearnCocos2D о минусах его использования). Хотя умножение на дельта-время позволяет вашему движению объекта более точно учитывать различную частоту кадров, как указал LearnCocos2d, было бы разумно избегать его использования в игре в реальном времени, где системные прерывания (новая почта, низкий заряд батареи, всплывающая реклама) -out) может произойти, что впоследствии приведет к тому, что симуляция игры перескочит вперед в попытке наверстать упущенное.

Поэтому, если вы опускаете dt, не забудьте соответствующим образом настроить (уменьшить) значение GRAVITY, чтобы сохранить правильное ощущение, поскольку это значение больше не умножается на значение дельта-времени (которое составляет ~ 1/60).

Дополнительный совет: чтобы применить импульс для перемещения спрайта (скажем, с помощью свайпа), вы можете напрямую влиять на скорости, изменяя значения Velocity_x (если они у вас есть) и Velocity_y.

Я использовал этот подход в своих играх, и он работает очень хорошо. Надеюсь, поможет.

person Ken Toh    schedule 14.07.2012
comment
Я хотел бы добавить, что это также работает без умножения на дельта-время. Вы можете захотеть избежать дельта-времени, потому что любое падение частоты кадров будет поддерживать движение объекта с той же скоростью, но игрок должен быстрее реагировать на изменения и может быть не в состоянии из-за более низкой частоты кадров. Также есть побочный эффект, если, например, фоновый процесс блокирует ЦП на 0,2 секунды, симуляция сильно перескакивает вперед. Опять же, это может легко убить игрока, потому что это неожиданно. Лично я предпочитаю замедлять всю симуляцию игры, поскольку частота кадров падает, не используя время dt. - person LearnCocos2D; 14.07.2012
comment
@Kentoh Не могли бы вы отредактировать свой пост, чтобы он включал советы, которые дал LearnCocos2D? Пока ваш код выглядит великолепно, но я хочу, чтобы в нем было как можно меньше ошибок! - person SimplyKiwi; 14.07.2012
comment
Также не могли бы вы показать, как вы объявили эти переменные в .h и удалили скорость X, поскольку мне нужно только значение Y? :П - person SimplyKiwi; 15.07.2012
comment
Обновление: я добавил награду в 100 баллов. Если @LearnCocos2D знает, как правильно применять гравитацию, не стесняйтесь добавлять это в качестве ответа! - person SimplyKiwi; 18.07.2012
comment
@iBradApps, я обновил ответ. Вы можете объявить Velocity_y где угодно, даже в заголовке игрового класса, если у вас есть только один спрайт, к которому вы хотите применить гравитацию. В противном случае вы можете создать подкласс CCSprite и добавить его в качестве члена, чтобы вы могли, например, выполнить mysprite.velocity_y. Надеюсь это поможет. - person Ken Toh; 20.07.2012
comment
Спасибо @kentoh, я попробую это позже! Только один вопрос, гравитация со временем будет увеличиваться, как и в реальной жизни, верно? - person SimplyKiwi; 20.07.2012
comment
Гравитация должна быть постоянной, как и в реальной жизни, где все ускоряется по направлению к земле с гравитационным значением 9,81 м/с2. Это скорость падающего объекта, которая должна увеличиваться со временем в результате постоянного ускорения. Так что держите его постоянным! - person Ken Toh; 20.07.2012
comment
Хорошо, спасибо, последний вопрос. Как правильно сбросить гравитацию, чтобы мой спрайт не падал? Допустим, он сталкивается с полом, мне нужно остановить падение персонажа, так как же мне правильно остановить гравитацию с помощью вашего кода? - person SimplyKiwi; 21.07.2012
comment
Кроме того, в настоящее время я реализовал фиксированный временной шаг в своей игре, поэтому будет ли нормально использовать дельта-время, поскольку тогда все будет замедлено? - person SimplyKiwi; 21.07.2012
comment
Гравитация должна оставаться постоянной даже при столкновении. Что вам нужно сделать, так это реализовать правильное обнаружение столкновений для вычисления новых значений скорости_y, что может быть нетривиально, в зависимости от формы объекта. Если тело можно рассматривать как сферу и предполагая упругое столкновение, простой подход на основе импульса состоит в том, чтобы отрицать значение вашей y-скорости при контакте (или уменьшать значение скорости, если оно неупругое). - person Ken Toh; 21.07.2012
comment
Моя гравитация не должна быть такой глубокой. 1) Если я хочу просто иметь простой способ сбросить гравитацию. Разве я не могу просто сделать Velocity_y = 0; ? 2) Также могу ли я использовать дельта-время, если я использую фиксированный временной шаг в своей игре, не сведет ли это на нет недостатки, о которых сказал LearnCocos2D? - person SimplyKiwi; 21.07.2012

Это не тривиальный вопрос, вы должны попытаться увидеть другие сообщения. Я уверен, что у других людей уже была эта проблема. Попробуйте посмотреть:

Или попробуйте наш хороший друг Google:

В любом случае, вот несколько советов:

Шаг 1, рассчитать векторы эффективного направления Шаг 2, вычислить скорость Шаг 3, спроецировать эту скорость на два эффективных направления. Шаг 4, создайте равную и противоположную силу для двух направлений и назовите это «силой отклика».

person An-droid    schedule 20.07.2012