Столкновения между игровыми объектами и полом из-за гравитации?

Как игры с гравитацией управляют отношениями между движущимися вещами, такими как игроки, монстры или объекты, и полом? Игрок постоянно «падает» на пол и отскакивает обратно?

Я обнаружил два способа реагировать на столкновения: вернуть игрока в его предыдущее положение перед столкновением и проверить новое положение перед перемещением, чтобы увидеть, не приведет ли это к столкновению, но я не понимаю, как ни один из этих способов может иметь дело с платформой, которая поднимается вверх и должна быть в состоянии поднять игрока. Я смотрю на это с точки зрения дизайна 2D-игр, но мне кажется, что та же проблема возникает и в дизайне 3D-игр. Любые подсказки? Любые ссылки, которые я должен проверить? Спасибо.


person Andru Luvisi    schedule 13.01.2009    source источник


Ответы (5)


Вы можете просмотреть Часто задаваемые вопросы о Gravity на GameDev.net, чтобы получить основную информацию.

Поскольку вы делаете игру, а не являетесь высокоточным специалистом по моделированию физики, нам может сойти с рук интеграция Эйлера. . Если ваша потребность в точности возрастает, наиболее популярным методом интеграции, который я вижу, является Runge-Kutta (RK4 ) интеграция. Вам, скорее всего, они не понадобятся для простой игры, но они определенно используются в более продвинутом физическом моделировании и 3D-играх. Недостатком использования RK4 является немного повышенная сложность и немного медленнее. Хотя это очень точно, но пока давайте придерживаться старого доброго Эйлера.

Я задал аналогичный вопрос: «Как применить гравитацию к моей игре с прыгающим мячом", и получил несколько хороших ответов. Первое, что вам нужно сделать, это выбрать произвольную гравитационную константу для вашей игры. В моем приложении с прыгающим мячом я использую гравитационную константу по умолчанию 2000 пикселей в секунду. Вы захотите поиграть с этой постоянной гравитации, чтобы получить желаемый эффект для вашей конкретной игры.

Затем вы хотите убедиться, что вы выполняете рендеринг своей игры и обновляете свои игровые объекты независимо. Это делается для того, чтобы ваши внутриигровые объекты не двигались очень быстро на быстрых компьютерах и медленно на медленных компьютерах. Вы хотите, чтобы физика и скорость, с которой перемещаются ваши объекты, не зависели от скорости компьютера. Хорошая статья на эту тему: Game Physics: Fix your timestep! .

Итак, как мы это делаем? Вы отслеживаете, сколько времени прошло с момента последнего вызова вашего метода Update. Я создал 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's velocity vector
        gameObject.position.x += (gameObject.velocity.x * elapsedSeconds); 
        gameObject.position.y += (gameObject.velocity.y * elapsedSeconds);

    }

    checkCollisions();

    previousTime = currentTime;
}

Это будет перемещать все ваши объекты на основе их векторов скорости и применять к ним гравитацию на основе вашей гравитационной константы. Лучше всего он делает это независимо от скорости компьютера!

Чтобы ответить на ваш другой вопрос, да, объекты будут постоянно иметь «силу» гравитации на их векторе y. Так что он будет постоянно сталкиваться с полом. Однако одна вещь, которую вы хотите сделать, это использовать значение эпсилон, чтобы в конечном итоге довести скорость вашего игрового объекта до нуля. Затем, во время обнаружения столкновений, как часть вашего процесса обрезки, вы обычно можете пропустить проверку, сталкивается ли неподвижный объект с чем-либо (но не наоборот!).

Что мне нравится делать со столкновениями, так это то, что когда я нахожу объекты, сталкивающиеся (проникающие друг в друга), я раздвигаю их на расстояние их минимального перемещения (MTD), которое их разделяет. Этот шаг является ключевым, в противном случае вы получите часто встречающуюся ошибку в играх, когда объекты «слипаются» вместе и трясутся. Как только они разделены, я вычисляю реакцию на столкновение.

Используя этот метод, он будет отлично работать в описанном вами сценарии подъема платформы. Платформа продолжит подниматься, игровой объект отделится с помощью МПД между собой и платформой и естественным образом поднимется вместе с ней.

Если вам нужна помощь в ответе на столкновение, я бы посоветовал посмотреть:

person mmcdole    schedule 13.01.2009
comment
Мне пришлось напечатать этот ответ дважды, лол. Должен быть какой-то аддон Firefox, который не позволяет кнопке «Вперед / Назад» очищать поля. Ооочень расстраивает. - person mmcdole; 13.01.2009

Один из подходов, используемых в некоторых играх, заключается в читерстве: отдельное состояние для ходьбы и в воздухе. Во время ходьбы игровой движок может определять наклон поверхности, по которой ходят, и, если он не слишком крутой, перемещать персонажа в направлении поверхности, а также придавать персонажу правильное вертикальное положение относительно поверхности.

Что касается физики, я становлюсь поклонником интеграции verlet, как описано в Gamasutra: Advanced Character Физика. Это упрощает уравнения обновления физики (не нужно отслеживать скорость!) и упрощает столкновения (не нужно регулировать скорость!). Тем не менее, у него есть несколько нюансов, если вам нужна точность.

person Paul    schedule 13.01.2009

Одним из наиболее полных учебников по этому предмету является Обнаружение столкновений в реальном времени от Кристера Эриксона. У него также есть сопутствующий блог. Математика для программирования 3D-игр и компьютерной графики< /em> тоже полезен.

person Crashworks    schedule 13.01.2009

Я не специально программист игр, но это мое понимание:

  • в идеальном мире с «бесконечной частотой кадров» вы бы обнаружили столкновение именно в тот момент, когда оно произошло, и использовали немного стандартной физики для моделирования новых скоростей и ускорений тел после столкновения (см. школьный учебник по механике или разные книги с названиями типа "Физика для программистов игр")
  • на самом деле, поскольку у вас фиксированная частота кадров и, следовательно, тела движутся только с определенной степенью детализации, вам обычно нужно добавить дополнительный прием, например, заранее рассчитать относительный путь, по которому тела будут двигаться в следующем кадре, и посмотреть, есть ли какие-либо из них. пути пересекаются
  • если они пересекаются, то точка пересечения фактически будет оценкой, хотя и несколько неточной, точки, в которой тела действительно столкнулись бы; тогда у вас есть выбор: не обращать внимания и принять эту оценку как точку пересечения и линейно интерполировать, чтобы получить скорости в точке столкновения, или выполнить более точный расчет теперь, когда вы узнали, что они будут пересекаться, чтобы получить фактическая точка/время/скорость столкновения
person Neil Coffey    schedule 13.01.2009

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

person Sparr    schedule 13.01.2009