2010-10-10 3 views
6

Я работаю над 3D-плиткой, и я использую обнаружение столкновений AABB. Для каждого куба, который игрок пересекает, я нахожу ось, по которой игрок меньше всего пересекает куб, и выталкивает игрока из куба вдоль этой оси.Скользящее столкновение AABB - застревание на краях

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

http://imgur.com/mmK0W.png

  • Arrow # 1 является попытка движения игрока. Другие стрелки - это реакция столкновения.
  • На левой диаграмме столкновение сначала проверяется на правый куб, заставляя игрока перемещаться влево, а затем вверх. (bad)
  • На правой диаграмме столкновение сначала проверяется против левого куба, заставляя игрока выдвигаться вверх, после чего игрок больше не пересекает другой куб. (хорошо)

Любые идеи о том, что наиболее эффективный способ решения этой проблемы может быть? Или любые лучшие способы обработки реакции столкновения?

спасибо.

+3

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

+0

Итак, если бы я отсортировал все кубы, которые игрок пересекал на расстоянии от игрока, а затем рассмотрел один за раз, это может сработать. Я думаю, было бы лучше избегать необходимости сортировать вещи в каждом фрейме, но я не уверен, что это будет иметь большое значение, поскольку игрок может столкнуться только с результатом до 7? блоков за один раз. Как вы думаете, есть ли что-то, что можно было бы там беспокоить? – Jeff

ответ

4

Дискретная реализация заставляет вас вводить некоторую непрерывную математику в систему, только когда требуется (кубы/направления перекрываются).

Для каждого куба c1, c2 ... CI, с которой кубик пользователь (УНЦ) пересекает в момент проверки, вы хотите узнать, какой куб был «прикоснулся» первым - есть только один, как в реальной жизни. Рассмотрим направление d из УНЦ, и, принимая количество ЯК в ХИ (дублирующих друг друга) найти положение у.е. в момент его «прикоснулся» CI.

Определить, куб был «прикоснулся» первый сг (тот, который требуется наибольший откат на d оси - чем раньше во времени) и использовать только этот один, чтобы вычислить реакцию столкновения.

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

+0

+1. Я сделал что-то вроде этого один раз, хотя это боль для реализации и отладки. Вы можете столкнуться с трудностями при использовании этого подхода, когда движение объектов из одного кадра в другое происходит не по линейной линии, а в противном случае оно работает очень хорошо. Вам нужно будет запомнить предыдущую позицию (и, возможно, предыдущую скорость) каждого объекта, который может перемещаться, чтобы вы могли рассчитать положение и скорость объектов в любой момент времени между двумя кадрами. – Cameron

+0

У меня проблемы с пониманием того, что вы говорите, но я думаю, что этот ответ также возникнет, если игрок попытается войти в угол комнаты. Я считаю, что необходимо учитывать более одного блока. Возможно, я мог бы отсортировать все блоки, с которыми сталкивается игрок, но я не уверен, было бы лучше избегать необходимости сортировать вещи. – Jeff

+0

Стена комнаты должна обрабатываться так же, как и другие кубики - это конкретный (более простой) случай: вы проверяете, не является ли куб вне границ, и, используя тот же алгоритм, определите, какая часть куба , вы проверяете столкновения с другими кубами. Опять же, первый «коснулся» (другой куб или стена) должен быть обработан реакцией столкновения. Стена - это особый недвижущийся и больший объект, с которым может столкнуться куб. –

0

На вашей диаграмме кажется, что вам нужен самый маленький ход, который минимизирует перекрытие между игроком и кубами. Каждый куб с перекрытием будет пытаться «нажимать» игрока в двух ортогональных направлениях. Можете ли вы сделать что-то вроде выбора минимального толчка максимальных нажатий в каждом направлении?

+0

Я думаю, что это может вызвать проблемы, если игрок идет в угол. В этом случае мне нужно нажать игрока назад на 2 оси. – Jeff

+0

Хорошо; мышление в 2D, толкание должно иметь вертикальный и горизонтальный компонент. Каждый перекрывающий куб может передавать толчок в двух направлениях из {N, S, E, W}. Если есть несколько перекрывающихся кубов, тогда вам нужно учитывать максимальные нажатия в направлениях {N, S} и {E, W} (что-то меньшее останется перекрытием, но можно игнорировать, скажем, NS-push, потому что нажатие EW выполнит задание). Существует не более восьми возможностей. Можете ли вы попробовать все восемь по порядку величины и выбрать первый, который очищает игрока от кубов? – Rafe

+0

К сожалению, в 3-х измерениях были бы еще более возможные наборы. Вероятно, было бы более эффективно сначала сортировать блоки на основе расстояния, как предложил Том. – Jeff

0

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

+0

Я пытаюсь подумать, как я применил бы это к 3 измерениям. Если бы у меня была форма, подобная «L», которая стояла, я мог бы объединить 2 блока по горизонтали или по вертикали. Но я думаю, что порядок, который я должен был бы применить, будет зависеть от позиции игрока или направления движения. – Jeff

0

Столкновение может нажимать объект только на 1 ось. Чтобы определить ось для нажатия:

else -- not this 
elseif -- change to this 

if w > h then 
    push x 
elseif h > w then 
    push y 
end 

Это работает, если ваши плитки выровнены.

Используйте круги, чтобы избежать палки по выровненной плитке

Смежные вопросы