В игре 2D-платформы, как обеспечить плавное движение игрока по наклонной поверхности?

18

Я разрабатываю физический движок для 2D-игры на платформе. Я использую теорему о разделительной оси для обнаружения столкновений. Поверхность земли состоит из ориентированных ограничивающих рамок, в которых игрок выступает в качестве ограничивающей рамки, ориентированной по оси. (В частности, я использую алгоритм из книги «Обнаружение столкновений в реальном времени», который выполняет развернутое обнаружение столкновений для OBB, использующих SAT). Я использую довольно маленький (близкий к нулю) коэффициент восстановления в реакции на столкновение, чтобы гарантировать, что динамические объекты не проникают в окружающую среду.

Двигатель в основном работает нормально, просто я обеспокоен некоторыми крайними случаями, которые могут возникнуть. Например, на диаграмме A, B и C - поверхность земли. Игрок направляется влево по B к A. Мне кажется, что из-за неточности поле игрока может быть немного ниже поля B, поскольку оно продолжается вверх и влево. Следовательно, когда он достигает A, нижний левый угол игрока может столкнуться с правой стороной A, что было бы нежелательно (так как намерение состоит в том, чтобы игрок плавно перемещался по верху A). Похоже, что подобная проблема может возникнуть, когда игрок находится в верхней части поля C, двигаясь влево к B - самая крайняя точка B может столкнуться с левой стороной игрока, вместо того, чтобы нижний левый угол игрока скользил вверх и влево выше Б.

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

Любые предложения будут ценны.

Ник Ковач
источник
Общий физический движок отлично подходит для эффектов и падающих коробок и всего такого, но не для физики персонажей, как изложено в разделе ответов. Подумайте о написании «статической» физики для вашего персонажа, чтобы вы могли контролировать его на 100%, а в остальном использовать правильно смоделированную динамику.
Доми

Ответы:

14

Платформа и физика

Эти крайние случаи многочисленны. Хорошие забавные платформеры не ведут себя физически точным образом, а управление и поведение, которого ожидают игроки после многих лет «совершенных» платформеров, таких как Mario, невероятно сложно реализовать с помощью общих методов, таких как Box2D или другие физические движки. Большинство хороших платформеров не используют какую-либо общую физику или реакцию на столкновение в своих контроллерах игроков.

Генерировать корпуса

Что касается вашего конкретного вопроса, лучшее решение состоит в том, чтобы прекратить использовать коробки в качестве основы. Используйте серию соединенных отрезков (корпус). Это позволяет механизму обнаружения столкновений фокусироваться только на реально проходимых поверхностях, а не смотреть на «фальшивый» край, который существует между AB и BC. Именно это и делает Box2D. Формы используются для создания внешних поверхностей, которые связаны вместе, чтобы сформировать корпус.

Это необходимо даже в играх на основе тайлов или в ситуациях, когда у вас есть два объекта AABB рядом с другими, выступающими в качестве пола. Движок столкновения подхватит эти вертикальные края и заставит игрока ловить их. Есть взломы, которые могут помочь, но не устранить проблему. Решение состоит в том, чтобы иметь только один отрезок, представляющий поверхность, а не полный 2D-блок.

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

Наклонные поверхности

Поскольку ваш пример включает в себя уклон, и вы упоминаете реституцию и другие физические свойства, я укажу на несколько других проблем, которые вы скоро заметите, что дополнительно иллюстрирует, почему общее обнаружение столкновений и реагирование не работают хорошо для платформеров. Сначала попытайтесь встать на наклонную платформу, подпрыгните, а затем приземлитесь. Вы, вероятно, заметите, что персонаж немного «скользит» при приземлении. Проблема в том, что нормальный контакт, который вы генерируете, обычно будет направлен от наклонной поверхности. Затем при разрешении столкновения игрок выталкивается в этом направлении. Даже если персонаж упал прямо вниз, он будет толкаться вверх и немного вправо при приземлении, что приведет к скольжению. Это можно взломать, принимая во внимание относительные скорости,

Вторая проблема, которую вы заметите, решить которую гораздо сложнее, - это то, что происходит, когда вы пытаетесь быстро спуститься по трапу. Игрок собирается «прыгать» вниз по трапу. Это очень заметно даже в большинстве игр ААА сегодня. Это не только выглядит глупо, но если ваша игра требует, чтобы игрок был на ногах по земле, чтобы прыгать, это затрудняет бег по рампе и прыжок на полпути, потому что игрок контактирует с рампой только в течение небольшой части время потраченное на это. Более простой способ - просто сделать несколько лучей, когда игрок двигается, и привязать положение игрока к ближайшей поверхности (если оно очень близко к игроку), если игрок не прыгает и ранее находился на земле.

Вы также можете обнаружить, что игрок запускается в воздух, когда бежит по рампе, если вы пытаетесь смоделировать скорость, трение и восстановление на игроке, как если бы он был обычным твердым телом. Движение игрока должно быть ограничено горизонтальным движением, кроме случаев падения / прыжка. Конечно, если вы играете в старые платформеры золотого века, вы можете заметить, что горизонтальная скорость игрока часто постоянна между горизонтальными и наклонными поверхностями. Это необходимо учитывать при ходьбе вверх / вниз по склонам.

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

Шон Миддледич
источник
Спасибо за ответ. Я подумывал о том, чтобы уменьшить прямоугольники, которые представляют землю, на линии, но на самом деле я не думаю, что это само по себе решит проблему. Например, если наземные боксы теперь являются линиями, и если игрок стоит на линии C и движется влево к B, из-за неточности возможно, что бокс игрока находится немного ниже линии C. Затем левый край бокса игрока все еще может столкнуться с линией B и вызвать это нежелательное столкновение,
Ник Ковач
если нет какого-то другого механизма, чтобы остановить это. Проблема не в том, что Box2D использует линии вместо блоков, что решает проблему, а в том, что Box2D использует форму цепи, которая использует информацию о соединении между сегментами линии, чтобы предотвратить некоторые столкновения. Основная проблема на данный момент в том, что я не совсем понимаю, как именно это происходит.
Ник Ковач
Вы затронули и другие действительно хорошие вопросы о проблемах, связанных с извлечением идей из обычных физических движков и их применением в играх на платформе. Я видел подобные движки, которые реализуют идеи, которые вы обсуждали (изменение нормального столкновения для уклонов и засасывание игрока на уклон), так что, по крайней мере, эти проблемы довольно легко решаемы. Основным камнем преткновения для меня являются сложные граничные случаи, связанные с числовыми ошибками.
Ник Ковач
@Kovsa: опять же, эти конкретные ошибки исчезают, когда вы избавляетесь от краев, которые не должны быть частью столкновения с самого начала. Цепные края вместе, чтобы сформировать непрерывную форму. При разработке вашего уровня, я бы также порекомендовал соединить вершины вместе, чтобы у вас не было мелких трещин на поверхностях. На самом деле ничем не отличается от того, как вы проектируете уровень в редакторе трехмерных сеток.
Шон Мидлдич
Хм ... я не думаю, что я следую. На моей диаграмме, если я соединю ребра вместе, чтобы получить непрерывную форму, я получу фигуру, состоящую из трех отрезков линии: вершины прямоугольников A, B и C, верно? Несмотря на то, что это одна фигура, мне все равно нужно было бы выполнять обнаружение столкновений отдельно по линии A, затем B, затем C, не так ли? Разве вы не имели в виду алгоритм, который может обнаружить столкновение между коробкой и этой комбинированной формой? Я предполагаю, что это не будет SAT, так как ряд ребер может быть вогнутым?
Ник Ковач
5

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

Таким образом, если игрок, двигаясь влево, попадет в угол A, нормаль столкновения будет диагональной, а не только вправо, что позволит продолжить движение влево-вверх.


Однако, при рассмотрении того, что я знаю о физике платформеров, более типичным решением является сделать игрока более округлой формой и оставить ландшафт в покое. В частности, подумайте о том, чтобы сделать форму игрока капсулой (растянутый в середине круг (2D) / сфера (3D)) - тогда ваши нормали столкновения будут, естественно , почти вертикальными, что устраняет любую проблему с зацеплением.

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

Кевин Рид
источник
Хм, интересная идея ... как бы вы ее реализовали? Хотя это несколько противоречит простоте использования блоков: (Я согласен, что кажется, что это должно быть общей проблемой с окончательным решением, но я не могу найти какое-либо освещение по этому поводу на самом деле ... кроме того, что делается в Box2D. Я разместил похожий вопрос на их форуме, чтобы, надеюсь, получить больше информации
Ник Ковач,
У меня нет подробностей реализации, извините - я не эксперт по этому виду кода физического движка. Однако у меня была лучшая идея для решения, которое не основано на факторах выдумки - см. Мое редактирование.
Кевин Рид,
1
Обратите внимание, что хотя использование округлых форм действительно работает, это математически более сложно и может привести к неоптимальному поведению для платформеров. Например, игроки ожидают почти идеального контроля над персонажами, стоящими на уступах, из-за которых округлые формы станут более или менее невозможными, а персонажи неожиданно соскользнут с выступов.
Шон Мидлдич
Уступы: D'Oh! ОК, не так просто, как я думал.
Кевин Рейд
Да, подумав об этом, капсульный подход, возможно, больше подходит для 3D-игр, чем для 2D-платформеров. Наличие идеального контроля пикселей определенно является для меня приоритетом (как это было во всех тех старых 2D-платформерах). Но должно быть решение, которое позволяет использовать коробки!
Ник Ковач