Я разрабатываю физический движок для 2D-игры на платформе. Я использую теорему о разделительной оси для обнаружения столкновений. Поверхность земли состоит из ориентированных ограничивающих рамок, в которых игрок выступает в качестве ограничивающей рамки, ориентированной по оси. (В частности, я использую алгоритм из книги «Обнаружение столкновений в реальном времени», который выполняет развернутое обнаружение столкновений для OBB, использующих SAT). Я использую довольно маленький (близкий к нулю) коэффициент восстановления в реакции на столкновение, чтобы гарантировать, что динамические объекты не проникают в окружающую среду.
Двигатель в основном работает нормально, просто я обеспокоен некоторыми крайними случаями, которые могут возникнуть. Например, на диаграмме A, B и C - поверхность земли. Игрок направляется влево по B к A. Мне кажется, что из-за неточности поле игрока может быть немного ниже поля B, поскольку оно продолжается вверх и влево. Следовательно, когда он достигает A, нижний левый угол игрока может столкнуться с правой стороной A, что было бы нежелательно (так как намерение состоит в том, чтобы игрок плавно перемещался по верху A). Похоже, что подобная проблема может возникнуть, когда игрок находится в верхней части поля C, двигаясь влево к B - самая крайняя точка B может столкнуться с левой стороной игрока, вместо того, чтобы нижний левый угол игрока скользил вверх и влево выше Б.
Box2D, похоже, решает эту проблему, сохраняя информацию о подключении для его краевых фигур, но я не совсем уверен, как он использует эту информацию для решения проблемы, и после просмотра кода я не совсем понимаю, что он делает.
Любые предложения будут ценны.
Ответы:
Платформа и физика
Эти крайние случаи многочисленны. Хорошие забавные платформеры не ведут себя физически точным образом, а управление и поведение, которого ожидают игроки после многих лет «совершенных» платформеров, таких как Mario, невероятно сложно реализовать с помощью общих методов, таких как Box2D или другие физические движки. Большинство хороших платформеров не используют какую-либо общую физику или реакцию на столкновение в своих контроллерах игроков.
Генерировать корпуса
Что касается вашего конкретного вопроса, лучшее решение состоит в том, чтобы прекратить использовать коробки в качестве основы. Используйте серию соединенных отрезков (корпус). Это позволяет механизму обнаружения столкновений фокусироваться только на реально проходимых поверхностях, а не смотреть на «фальшивый» край, который существует между AB и BC. Именно это и делает Box2D. Формы используются для создания внешних поверхностей, которые связаны вместе, чтобы сформировать корпус.
Это необходимо даже в играх на основе тайлов или в ситуациях, когда у вас есть два объекта AABB рядом с другими, выступающими в качестве пола. Движок столкновения подхватит эти вертикальные края и заставит игрока ловить их. Есть взломы, которые могут помочь, но не устранить проблему. Решение состоит в том, чтобы иметь только один отрезок, представляющий поверхность, а не полный 2D-блок.
Вы можете генерировать оболочки в общем случае, обрезая многоугольники друг против друга и соединяя точки клипов в списке ребер.
Наклонные поверхности
Поскольку ваш пример включает в себя уклон, и вы упоминаете реституцию и другие физические свойства, я укажу на несколько других проблем, которые вы скоро заметите, что дополнительно иллюстрирует, почему общее обнаружение столкновений и реагирование не работают хорошо для платформеров. Сначала попытайтесь встать на наклонную платформу, подпрыгните, а затем приземлитесь. Вы, вероятно, заметите, что персонаж немного «скользит» при приземлении. Проблема в том, что нормальный контакт, который вы генерируете, обычно будет направлен от наклонной поверхности. Затем при разрешении столкновения игрок выталкивается в этом направлении. Даже если персонаж упал прямо вниз, он будет толкаться вверх и немного вправо при приземлении, что приведет к скольжению. Это можно взломать, принимая во внимание относительные скорости,
Вторая проблема, которую вы заметите, решить которую гораздо сложнее, - это то, что происходит, когда вы пытаетесь быстро спуститься по трапу. Игрок собирается «прыгать» вниз по трапу. Это очень заметно даже в большинстве игр ААА сегодня. Это не только выглядит глупо, но если ваша игра требует, чтобы игрок был на ногах по земле, чтобы прыгать, это затрудняет бег по рампе и прыжок на полпути, потому что игрок контактирует с рампой только в течение небольшой части время потраченное на это. Более простой способ - просто сделать несколько лучей, когда игрок двигается, и привязать положение игрока к ближайшей поверхности (если оно очень близко к игроку), если игрок не прыгает и ранее находился на земле.
Вы также можете обнаружить, что игрок запускается в воздух, когда бежит по рампе, если вы пытаетесь смоделировать скорость, трение и восстановление на игроке, как если бы он был обычным твердым телом. Движение игрока должно быть ограничено горизонтальным движением, кроме случаев падения / прыжка. Конечно, если вы играете в старые платформеры золотого века, вы можете заметить, что горизонтальная скорость игрока часто постоянна между горизонтальными и наклонными поверхностями. Это необходимо учитывать при ходьбе вверх / вниз по склонам.
Будет много других странных случаев, с которыми вы тоже столкнетесь. Если вы пытаетесь сделать хороший платформер, лучше всего реализовать контроллер плейформера отдельно от физики и жестко задавать желаемое движение и поведение управления, а не полагаться на общую физику и алгоритм реагирования на столкновения.
источник
Я думаю, что обе проблемы могут быть решены путем обработки ваших блоков в целях реагирования на столкновения, как если бы они имели закругленные углы (такого же радиуса, как и ваша числовая ошибка). Это сделает эффективную комбинированную поверхность углов встречи между А и В и В и С более гладкой.
Таким образом, если игрок, двигаясь влево, попадет в угол A, нормаль столкновения будет диагональной, а не только вправо, что позволит продолжить движение влево-вверх.
Однако, при рассмотрении того, что я знаю о физике платформеров, более типичным решением является сделать игрока более округлой формой и оставить ландшафт в покое. В частности, подумайте о том, чтобы сделать форму игрока капсулой (растянутый в середине круг (2D) / сфера (3D)) - тогда ваши нормали столкновения будут, естественно , почти вертикальными, что устраняет любую проблему с зацеплением.
Вы говорите, что используете алгоритм столкновения специально для OBB, но вы все равно должны иметь возможность, после обнаружения коллизии OBB-OBB, провести дополнительный тест на фигуру, которая полностью находится внутри OBB.
источник