Реакция столкновения в 2D-игре с боковыми скроллерами, похожей на «Марио» - PullRequest
10 голосов
/ 13 июля 2011

Это сильно беспокоило меня в последние несколько недель.В это время я проводил исследования в Интернете, даже читал книги в разделе «Компьютеры» в Borders, чтобы попытаться найти ответ, но мне не повезло.

Я запрограммировал редактор 2D-уровней для видеоигр с боковой прокруткой.Теперь я хочу превратить это в игру, где у меня есть игрок, который может бегать и прыгать, чтобы исследовать уровень, похожий на «Марио».

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

См. Это изображение сценариев реакции на столкновение:

example http://dl.dropbox.com/u/12556943/collision_detection.jpg

Предположим, что векторы скорости в сценариях (1) и (2) равны (одинаковое направление и величина),Тем не менее, в сценарии (1) игрок ударяет по стороне блока, а в сценарии (2) игрок приземляется на вершину блока.Это позволяет мне сделать вывод, что определение реакции на столкновение зависит не только от вектора скорости игрока, но и от относительного положения игрока относительно сталкивающегося блока.Это приводит к моему первому вопросу: зная вектор скорости и относительное положение игрока, как я могу определить, с какого направления (слева, справа, сверху или снизу) игрок сталкивается с блоком?

Другая проблема, с которой я столкнулся, заключается в том, как определить реакцию на столкновение, если игрок сталкивается с несколькими блоками в одном кадре.Например, предположим, что в сценарии (3) игрок сталкивается с обоими этими блоками одновременно.Я предполагаю, что мне придется проходить через каждый блок, с которым сталкивается игрок, и соответственно корректировать реакцию каждого блока.Подводя итог, это мой второй вопрос: как мне реагировать на столкновение, если игрок сталкивается с несколькими блоками?

Обратите внимание, что я никогда не раскрывал язык, на котором я программирую;это потому, что я предпочел бы, чтобы вы не знали (ничего личного, хотя:]).Меня больше интересует псевдокод, чем просмотр кода для конкретного языка.

Спасибо!

Ответы [ 3 ]

10 голосов
/ 15 июля 2011

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

  1. После применения движения, проверьте и решитеколлизии.
  2. Определите плитки, которые игрок перекрывает, основываясь на ограничивающей рамке игрока.
  3. Перебирайте все эти плитки, выполняя следующее: (обычно это не очень много, если ваш игрок не огромен по сравнению сплитки вашего мира)
    1. Если проверяемая плитка не проходима:
      1. Определите, насколько далеко по осям X и Y игрок перекрывает непроходимую плитку
      2. Разрешите столкновение, переместив игрока из этой плитки только по мелкой оси (какая ось наименее проникает)
        • Например, если Y - мелкая ось, а столкновение - ниже, сдвиньтеигрок больше не может перекрывать эту плитку.
        • Примерно так: if(abs(overlap.y) < abs(overlap.x)) { position.y += overlap.y; } else { position.x += overlap.x; }
      3. Обновлять положение ограничивающего прямоугольника в зависимости от позиции игрока.новая позиция
      4. Переход к следующей плитке ...
    2. Если проверяемая плитка является проходимой, ничего не делать
  4. Если возможно, что разрешение столкновения может переместить игрока в другое столкновение, вам может понадобиться выполнить вышеуказанный алгоритм во второй раз.Или измените свой уровень.

XNA-версия этой логики находится в player.cs в функции HandleCollisions(), если вы заинтересованы в том, чтобы захватить их код, чтобы посмотреть, что они конкретно там делают.

3 голосов
/ 13 июля 2011

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

Я думаю, вы захотите отделить две силы тяжести и скорость игрока от алгоритма обнаружения столкновения / реакции.Используя скорость игрока, если он сталкивается с блоком, независимо от направления, просто переместите положение игрока к краю столкновения и вычтите равный и противоположный вектор из скорости игрока, так как если этого не сделать, они снова столкнутся собъект.Вы можете рассчитать точку пересечения и разместить там положение игрока на блоке.

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

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

Я думаю, что, разделив эти две концепции, вы получите действительно простой алгоритм прямого отклика на столкновение и довольно простой алгоритм гравитационного пола.Таким образом, вы можете изменять гравитацию без необходимости переделывать свой алгоритм реагирования на столкновения.Скажем, например, уровень воды, уровень пространства и т. Д., И реакция обнаружения столкновений одинакова.

2 голосов
/ 13 июля 2011

Недавно я долго думал об этом.

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

Возможно, это не тот ответ, который вы ищете, но, надеюсь, он укажет вам правильное направление

...