Я пытаюсь внедрить систему столкновений в 2D-игру, которую я делаю. Теорема о разделяющей оси (как описано в учебнике по столкновению с metanet ) кажется эффективным и надежным способом обработки обнаружения столкновений, но мне не совсем нравится метод реагирования на столкновения, который они используют. При слепом смещении вдоль оси наименьшего перекрытия алгоритм просто игнорирует предыдущую позицию движущегося объекта, что означает, что он не сталкивается со стационарным объектом так сильно, как входит в него и затем отскакивает.
Вот пример ситуации, когда это будет иметь значение:
Согласно методу SAT, описанному выше, прямоугольник просто выпадет из треугольника, перпендикулярного его гипотенузе:
Однако реально, прямоугольник должен остановиться в нижнем правом углу треугольника, так как это будет точка первого столкновения, если он будет непрерывно двигаться вдоль своего вектора смещения:
Теперь, это может на самом деле не иметь значения во время игры, но я хотел бы знать, есть ли способ эффективно и вообще добиться точных перемещений таким образом. Последние несколько дней я ломал голову над этим, и пока не хочу сдаваться!
(Перекрестная публикация от StackOverflow, надеюсь, это не противоречит правилам!)
Ответы:
Вот метод, который я нашел. Это может быть ошибочным, но я не нашел никаких проблем с ним в моем кратком анализе. Это также работает для произвольных многоугольников с небольшими изменениями.
На рисунках ниже синий объект движется, а красный объект неподвижен. Шаг 1: Для каждого многоугольника найдите две самые дальние точки вдоль проекции этого многоугольника на линию, перпендикулярную вектору движения. Шаг 2: Разделите каждый многоугольник вдоль линии, соединяющей эти точки. Половина многоугольника, которая обращена к другому многоугольнику вдоль вектора движения, является "передней оболочкой". Это единственная часть многоугольника, которая может столкнуться. Шаг 3:Спроецируйте вектор из каждой точки "передней оболочки" каждого многоугольника вдоль вектора движения в направлении противоположного многоугольника и проверьте его на предмет пересечения с каждым ребром "передней оболочки" противоположного многоугольника. (Возможно, медленный, но в наше время компьютеры работают довольно быстро - верно?) (Извините за наклонную стрелку. Все стрелки должны быть параллельны.) Шаг 4: Возьмите кратчайший вектор. Это точное расстояние столкновения. Шаг 5: Вуаля!
источник
Проверьте этот похожий вопрос: разрешение столкновений
А также с http://www.metanetsoftware.com/technique/tutorialA.html#section5 (на которую вы разместили ссылку :))
РЕДАКТИРОВАТЬ
В итоге и AFAIK, есть несколько решений
источник
Это зависит от того, хотите ли вы только линейного движения или же вам нужно справиться с угловым движением.
Альтернатива использованию SAT:
Только в случае линейного можно навести луч на разность Минковского двух полигонов от начала координат в направлении дельта-линейной скорости объектов.
Если луч достигнет MD, два объекта столкнутся, и точка попадания сообщит вам время t, в которое они столкнулись.
Теперь, если объекты движутся и вращаются это становится сложнее, но вы все равно можете использовать аналогичную технику. Консервативное продвижение позволит вам разобраться с этим делом. Эта техника итеративна; каждая итерация будет генерировать новый MD и приближать вас к моменту пересечения.
Вот оригинальный проект документа по консервативному продвижению:
http://www.continuousphysics.com/BulletContinuousCollisionDetection.pdf
Я написал статью, объясняющую технику в некоторых деталях здесь:
http://www.wildbunny.co.uk/blog/2011/04/20/collision-detection-for-dummies/
Надеюсь, что это поможет!
источник