Как я могу реализовать гравитацию? Не для определенного языка, просто псевдокод ...
software-engineering
physics
Пиццирани Леонардо
источник
источник
Ответы:
Как отмечали другие в комментариях, базовый метод интеграции Эйлера, описанный в ответе tenpn, страдает от нескольких проблем:
Даже для простых движений, таких как баллистические прыжки в условиях постоянной силы тяжести, это приводит к систематической ошибке.
Ошибка зависит от временного шага, что означает, что изменение временного шага систематически меняет траектории объекта, что может быть замечено игроками, если игра использует переменный временной шаг. Даже для игр с фиксированным временным шагом физики изменение временного шага во время разработки может заметно повлиять на физику игры, например, на расстояние, на которое пролетит объект, запущенный с заданной силой, что может нарушить ранее спроектированные уровни.
Это не сохраняет энергию, даже если основная физика должна. В частности, объекты, которые должны постоянно колебаться (например, маятники, пружины, вращающиеся планеты и т. Д.), Могут неуклонно накапливать энергию, пока вся система не развалится.
К счастью, нетрудно заменить интеграцию Эйлера чем-то, что почти так же просто, но при этом не имеет ни одной из этих проблем - в частности, симплектического интегратора второго порядка, такого как интеграция с перепрыгиванием или близкий по скорости метод Верле . В частности, где базовая интеграция Эйлера обновляет скорость и положение как:
метод скорости Verlet делает это так:
Если у вас есть несколько взаимодействующих объектов, вы должны обновить все их позиции, прежде чем пересчитывать силы и обновлять скорости. Новое ускорение может быть сохранено и использовано для обновления позиции на следующем временном шаге, уменьшая количество вызовов
force()
до одного (на объект) за временной шаг, как в методе Эйлера.Кроме того, если ускорение обычно является постоянным (например, гравитация во время баллистического прыжка), мы можем упростить вышеупомянутое просто:
где дополнительный термин, выделенный жирным шрифтом, является единственным изменением по сравнению с базовой интеграцией Эйлера.
По сравнению с интеграцией Эйлера, методы скорости Верле и чехарды имеют несколько приятных свойств:
Для постоянного ускорения они дают точные результаты (в любом случае, вплоть до ошибок округления с плавающей запятой), а это означает, что траектории баллистических прыжков остаются неизменными даже при изменении временного шага.
Они являются интеграторами второго порядка, что означает, что даже при различном ускорении средняя ошибка интегрирования пропорциональна квадрату временного шага. Это может позволить большие временные шаги без ущерба для точности.
Они симплектичны , что означает, что они сохраняют энергию, если физика, лежащая в основе (по крайней мере, пока временной шаг постоянен). В частности, это означает, что вы не будете получать такие вещи, как планеты, спонтанно вылетающие с их орбит, или объекты, прикрепленные друг к другу с помощью пружин, постепенно качающиеся все больше и больше, пока все это не взорвется.
Тем не менее, метод определения скорости Верлета / перепрыгивания почти такой же простой и быстрый, как и базовая интеграция Эйлера, и, конечно, намного проще, чем альтернативы, такие как интеграция Рунге-Кутты четвертого порядка (которая, хотя и является очень хорошим интегратором, лишена симплектического свойства и требует четырех оценок). от
force()
функции на шаг по времени). Поэтому я настоятельно рекомендую их всем, кто пишет код игровой физики, даже если это так же просто, как переход с одной платформы на другую.Изменить: Хотя формальный вывод метода Верле скорости действителен только тогда, когда силы не зависят от скорости, на практике вы можете использовать его очень хорошо, даже с зависимыми от скорости силами, такими как сопротивление жидкости . Для достижения наилучших результатов вы должны использовать начальное значение ускорения для оценки новой скорости для второго вызова
force()
, например:Я не уверен, имеет ли этот конкретный вариант метода скорости Verlet конкретное имя, но я проверил его и, похоже, он работает очень хорошо. Он не так точен, как Рунге-Кутта четвертого порядка (как можно было бы ожидать от метода второго порядка), но он намного лучше, чем Эйлер или наивный метод скорости Верле без промежуточной оценки скорости, и все же сохраняет симплектическое свойство нормальной скорость Верле для консервативных, не зависящих от скорости сил.
Редактировать 2: Очень похожий алгоритм описан, например, Groot & Warren ( J. Chem. Phys. 1997) , хотя, читая между строк, кажется, что они пожертвовали некоторой точностью ради дополнительной скорости, сохранив
newAcceleration
значение, вычисленное с использованием расчетной скорости. и повторно использовать его вacceleration
качестве следующего шага. Они также вводят параметр 0 ≤ λ ≤ 1, который умножаетсяacceleration
на начальную оценку скорости; по какой-то причине они рекомендуют λ = 0,5, хотя все мои тесты показывают, что λ= 1 (что я и использую выше) работает так же или лучше, с повторным использованием ускорения или без него. Возможно, это как-то связано с тем, что их силы включают в себя компонент стохастического броуновского движения.источник
force(time, position, velocity)
моем ответе выше просто сокращение для "силы, действующей на объект приposition
движении вvelocity
attime
". Как правило, сила будет зависеть от того, находится ли объект в свободном падении или сидит на твердой поверхности, какие-либо близлежащие объекты оказывают на него силу, как быстро он движется по поверхности (трение) и / или через жидкость или газ (перетащить) и т. д.Каждый цикл обновления вашей игры, сделайте это:
Например, в платформер, когда вы прыгаете, гравитация будет включена (collidingBelow сообщает вам, есть ли земля прямо под вами), и когда вы упадете на землю, она будет отключена.
Кроме того, чтобы реализовать переходы, сделайте следующее:
И, очевидно, в цикле обновления вы также должны обновить свою позицию:
источник
Надлежащая независимая от частоты кадров * ньютоновская физическая интеграция:
Настраивайте тяготение Constant, motionConstant и massConstant, пока не почувствуете себя правильно. Это интуитивно понятная вещь, и может потребоваться некоторое время, чтобы почувствовать себя прекрасно.
Легко расширить вектор сил, чтобы добавить новый игровой процесс - например, добавить силу от любого ближайшего взрыва или к черным дырам.
* редактировать: эти результаты будут неправильными с течением времени, но могут быть «достаточно хорошими» для вашей верности или способностей. Смотрите эту ссылку http://lol.zoy.org/blog/2011/12/14/understanding-motion-in-games для получения дополнительной информации.
источник
position += velocity * timestep
выше наposition += (velocity - acceleration * timestep / 2) * timestep
(гдеvelocity - acceleration * timestep / 2
просто среднее значение старой и новой скоростей). В частности, этот интегратор дает точные результаты, если ускорение постоянное, как это обычно бывает для гравитации. Для повышения точности при изменяющемся ускорении вы можете добавить аналогичную поправку к обновлению скорости, чтобы получить интеграцию скорости с Верлетом .Если вы хотите реализовать гравитацию в несколько большем масштабе, вы можете использовать этот вид расчета для каждого цикла:
Для еще больших (галактических) масштабов одной гравитации недостаточно для создания «реального» движения. Взаимодействие звездных систем в значительной и очень заметной степени продиктовано уравнениями Навье-Стокса для гидродинамики, и вам придется учитывать конечную скорость света - и, следовательно, гравитацию - также.
источник
Код, предоставленный Ильмари Кароненом, почти верен, но есть небольшой сбой. Вы фактически вычисляете ускорение 2 раза за такт, это не соответствует уравнениям учебника.
Следующий мод правильный:
Приветствия
источник
Ответ Пеканта игнорировал время кадра, и это время от времени отличало ваше физическое поведение.
Если вы собираетесь сделать очень простую игру, вы можете создать свой собственный маленький физический движок - назначить массу и все виды физических параметров для каждого движущегося объекта, а также выполнить обнаружение столкновений, а затем обновлять их положение и скорость в каждом кадре. Чтобы ускорить этот прогресс, вам нужно упростить сетку столкновений, уменьшить количество вызовов обнаружения столкновений и т. Д. В большинстве случаев это проблема.
Лучше использовать физический движок, такой как Physix, ODE и Bullet. Любой из них будет стабильным и достаточно эффективным для вас.
http://www.nvidia.com/object/physx_new.html
http://bulletphysics.org/wordpress/
источник