Как я могу обнаружить, что игрок был раздавлен в 2D платформере?

19

Я проверяю столкновение для персонажа платформера, как показано в # 1. Красные точки - это проверенные пиксели, а серые линии обозначают оси, к которым они относятся. Мне нравятся результаты, которые я получаю от проверки столкновения таким образом (в отличие от, скажем, ограничивающего прямоугольника). Все работает именно так, как я хотел бы, за исключением одной проблемы: обнаружение раздавливания.

На следующих изображениях голубой прямоугольник представляет землю, оранжевый прямоугольник - объект, а стрелки указывают направление движения.

Простое решение для определения, когда игрок сокрушен, состоит в том, чтобы видеть, срабатывают ли точки столкновения на противоположных сторонах. Если они есть, игрок сокрушен. В # 2 вы можете увидеть нормальный сценарий разгрома. Игрок заземлен, а верхние точки столкновения пересекаются с падающим объектом. Это вызывает влюбленность.

№ 3, 4 и 5 представляют проблемные сценарии. В # 3 игрок движется к объекту, который движется вверх. Правая точка столкновения поражает объект, вызывая столкновение и останавливая игрока.

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

Аналогичный сценарий показан в # 5. Два объекта находятся достаточно далеко друг от друга, чтобы очистить нижние точки столкновения, позволяя игроку упасть, но не настолько, чтобы позволить точкам бокового столкновения очиститься, вызывая нежелательное горизонтальное раздавливание.

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

введите описание изображения здесь

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

введите описание изображения здесь

IanLarson
источник

Ответы:

34

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

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

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

congusbongus
источник
13
+1 Учтите, что здесь действует блок, а не игрок. Так что если вы проверяете, не разрушает ли поле игрок, а не проверяет, не раздавлен ли игрок, проблему легче решить
Niels
А когда блоки не движутся? Теперь я понимаю, что поставил стрелки на блоки № 5, но это были два стационарных блока.
Ян Ларсон,
Если вы решите, что стационарные блоки не должны давить, просто убедитесь, что игрок не застрял и может сойти с дороги.
congusbongus
Ага, я ненавижу быть раздавленным двумя объектами, которые на самом деле удаляются друг от друга, только потому, что я сделал его идеальным с точки зрения пикселей и кадров, а разработчик был ленивым.
носорог
9

Пусть точки «теста на раздавливание» находятся внутри серого прямоугольника, показанного на вашем изображении № 1, то есть убейте игрока, только если вы обнаружите попадание в один из пикселей.

Петерис
источник
1
Вы имеете в виду дополнительные контрольные точки раздавливания "внутри" границ точек столкновения? Проблема, с которой я сталкиваюсь, заключается в том, что разрешение столкновений будет происходить на каждой оси, когда одна из его точек столкновения «сработает» до того, как у объекта появится шанс достичь внутренних контрольных точек.
Ян Ларсон,
6

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

Имея это в виду, идея иметь отдельные точки для горизонтального и вертикального столкновения просто не летает. Таким образом, ваши случаи 3 и 5 не существуют.

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

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

Грэхем
источник
3
Незначительный момент - вы не знаете, как выглядит его спрайт. Насколько мы знаем, это может быть именно так, как показано на изображениях выше, поэтому случаи 3 и 5 могут быть полностью действительными.
Алекс
1
Алекс прав. Я сделал правку, чтобы уточнить. Я согласен, что нет ничего хуже, чем непостоянные столкновения коробки. Я думаю, что я понимаю вашу точку зрения о том, чтобы не использовать отдельные точки для разных осей. Если я это сделаю, то этот пример превратится из восьми в четыре, по одному в каждом углу, правильно? Я на самом деле провел некоторое тестирование с учетом этого (с менее чем желаемыми результатами), но я сильно сомневаюсь в этом, так как разделение углов позволяет добиться практически идеального поведения, которое я ищу. Это действительно единственные проблемные сценарии, с которыми я столкнулся.
Ян Ларсон,
0

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

Это предполагает, что игрок не может толкнуть себя «в» объекты или землю.

Zamfi
источник
0

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

Кстати, если только ограниченное количество комбинаций фигур может столкнуться, может быть полезно предварительно рассчитать битовые карты «обнаружения столкновений», чтобы, если пиксель был установлен в первом спрайте со смещением (x1, y1) и во втором со смещением (x2, y2) секунды пиксель со смещением (x1-x2, y1-y2) будет установлен на карте столкновений. Такая предварительно рассчитанная карта столкновений позволит обнаруживать столкновения между двумя спрайтами, проверяя состояние одного пикселя в карте столкновений.

Supercat
источник
0

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

Acccumulation
источник
0

Я нахожусь рядом, чтобы работать до сих пор. Он не требует «внешней» информации о движении дробилок и решает проблему ложных срабатываний. Когда ложный положительный результат обнаружен, он рассматривается как столкновение (и это действительно так):

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

Если персонаж движется и раздавлен (столкновения на противоположных сторонах для входящего кадра), тогда снова проверьте на раздавливание в последнем кадре / координатах итерации:

  1. Если не подтверждено снова, то это происходит из-за собственного движения персонажа, и персонаж должен быть возвращен к последним координатам кадра / итерации, как при столкновении

  2. Если раздавливание подтверждено во второй раз, тогда продолжайте раздавливание.

Nikaas
источник