Проблемы столкновения 2D-платформера с обеими осями - PullRequest
4 голосов
/ 17 апреля 2010

Я работаю над небольшой 2D-платформерной / файтинг-игрой с C ++ и SDL, и у меня возникло немало проблем с обнаружением столкновений.

Уровни состоят из массива плиток, и я использую цикл for для прохождения каждого из них (я знаю, что это может быть не лучшим способом сделать это, и мне может понадобиться помощь в этом тоже). Для каждой стороны персонажа я перемещаю его на один пиксель в этом направлении и проверяю, нет ли столкновения (я также проверяю, движется ли персонаж в этом направлении). Если происходит столкновение, я устанавливаю скорость на 0 и перемещаю игрока к краю плитки.

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

Как я могу справиться со столкновениями на обеих осях без этих проблем? Есть ли лучший способ справиться со столкновением, чем то, как я это делаю?

Ответы [ 2 ]

3 голосов
/ 17 апреля 2010

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

  1. После применения движения он проверяет наличие столкновений.
  2. Определяет плитки, которые игрок перекрывает, основываясь на ограничительной рамке игрока.
  3. Он перебирает все эти тайлы ...
    1. Если проверяемая плитка не проходима:
    2. Определяет, как далеко по осям X и Y игрок перекрывает непроходимый тайл
    3. Столкновение разрешается только по мелкой оси :
      1. Если Y - пологая ось (abs (перекрытие y)
      2. Ограничительная рамка обновляется в зависимости от изменения позиции
    4. Переходите к следующей плитке ...

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

0 голосов
/ 17 апреля 2010

Да. Векторное столкновение будет намного лучше, чем основанное на плитке. Определите каждый край плитки как линии (есть короткие пути, но пока игнорируйте их.) Теперь, чтобы увидеть, произошло ли столкновение, найдите ближайшую горизонтальную и вертикальную линию. если вы берете знак lastPos.x * LineVector.y - lastPos.y * LineVector.x и сравниваете это с thisTurnsPos.x * LineVector.y - ThisTurnsPos.y * LinePos.x. Если знаки этих двух значений различаются, вы пересекли эту черту в этом тике. Это не проверяет, если вы пересекли конец отрезка линии, хотя. Вы можете сформировать точечное произведение между одним и тем же lineVector и вашим curPosition (здесь небольшая ошибка, но, вероятно, достаточно хорошая), и оно либо отрицательно, либо больше квадрата амплитуды линии, вы не находитесь внутри этого отрезка и не произошло столкновения .

Теперь это очень сложно, и вы, вероятно, могли бы уйти с простой проверкой сетки, чтобы увидеть, не перешли ли вы в область другого квадрата. Но! Преимущество работы с векторами состоит в том, что она решает движение быстрее, чем размер проблемы с коллизионным блоком, и (что более важно), вы можете использовать линии, не выровненные по оси, для ваших коллизий. Эта система работает для любых 2D векторов (и с небольшим массажем, а также для 3D). Она также позволяет довольно легко перемещать вашего персонажа по краю поля столкновения, потому что вы уже выполнили 99% математики, необходимой для найти, где вы должны быть после столкновения.

Я упустил из виду пару деталей реализации, но могу сказать, что я использовал вышеописанный метод в бесчисленных коммерческих видеоиграх, и он сработал как шарм. Удачи!

...