Ответ 1
Возможно, вы захотите проверить "Часто задаваемые вопросы о гравитации" GameDev.net для некоторой базовой информации.
Поскольку вы создаете игру, а не очень точный физический модельер, мы можем уйти с интеграции Euler. Если ваша потребность в точности увеличивается, самым популярным методом интеграции, который я использую, является интеграция Runge-Kutta (RK4). Скорее всего, вам это не понадобится для простой игры, но они определенно используются в более продвинутом физическом моделировании и 3D-играх. Недостаток использования RK4 несколько усложняется и немного медленнее. Это очень точно, хотя, но пока, давайте придерживаться хорошего ole Euler.
Я задал аналогичный вопрос: "Как применить гравитацию к моей прыгающей игре в мяч" и получил несколько хороших ответов. Первое, что вы сделаете, это выбрать произвольную гравитационную константу для вашей игры. В моем приложении отбойного шара я использую стандартную гравитационную константу 2000px/s. Вы хотите играть с этой постоянной силы тяжести, чтобы получить желаемый эффект для вашей конкретной игры.
Затем вы хотите удостовериться, что вы делаете свою игру и самостоятельно обновляете свои игровые объекты. Это необходимо для того, чтобы ваши внутриигровые объекты быстро перемещались на быстрых компьютерах и замедлялись на медленных компьютерах. Вам нужна физика и скорость, с которой ваши объекты перемещаются, чтобы быть независимыми от скорости компьютера. Хорошая статья об этом - Игровая физика: исправьте свой timestep!.
Итак, как мы это делаем? Вы отслеживаете, сколько времени прошло с момента последнего вызова метода обновления. Я создал 2 потока, хотя это не обязательно. У меня есть поток обновления игры и поток рендеринга. Нить обновления контролирует обновление позиций в игровых объектах. Нить обновления знает, когда она была ранее вызвана, текущее время и от нее вычисляет прошедшее время с момента вызова метода обновления.
Чтобы применить гравитацию, мы просто добавим к скорости Y нашего объекта по нашей постоянной силы тяжести, умноженной на прошедшее время.
private long previousTime = System.currentTimeMillis();
private long currentTime = previousTime;
public void updateGame()
{
currentTime = System.currentTimeMillis();
float elapsedSeconds = (currentTime - previousTime) / 1000f;
foreach(GameObject gameObject in gameObjects)
{
// Apply gravity to velocity vector
gameObject.velocity.y += (gravityConstant * elapsedSeconds);
// Move objects x/y position based off it velocity vector
gameObject.position.x += (gameObject.velocity.x * elapsedSeconds);
gameObject.position.y += (gameObject.velocity.y * elapsedSeconds);
}
checkCollisions();
previousTime = currentTime;
}
Это переместит все ваши объекты на основе их вектора скорости и применит гравитацию к ним на основе вашей постоянной силы тяжести. Лучше всего он делает это независимо от скорости компьютера!
Чтобы ответить на ваш другой вопрос, да, объекты будут постоянно иметь "силу" силы тяжести на своем векторе y. Поэтому он будет постоянно сталкиваться с полом. Тем не менее, одна вещь, которую вы хотите сделать, это использовать значение Epsilon, чтобы в конечном итоге привести вашу скорость gameObject к нулю. Затем, во время обнаружения столкновения как части процесса обрезки, вы можете, как правило, пропускать проверку, если не движущийся объект сталкивается с чем-либо (не наоборот, хотя!).
То, что мне нравится делать с столкновениями, - это когда я нахожу объекты, сталкивающиеся (проникающие друг в друга), я раздвигаю их на минимальное расстояние передачи (MTD), которое их разделяет. Этот шаг является ключевым, иначе вы получите часто наблюдаемую ошибку в играх объектов, "застрявших" вместе, дрожащих движений. Когда они разделены, я вычисляю свой ответ на столкновение.
Используя этот метод, он будет отлично работать в описываемом сценарии восходящей платформы. Платформа будет продолжать расти, gameObject будет отделяться, используя MTD между собой и платформой, и она, естественно, будет расти вместе с ней.
Если вам нужна помощь в ответе на столкновение, я бы предложил посмотреть: