Избегайте сложности O (n ^ 2) для обнаружения столкновений - PullRequest
10 голосов
/ 04 февраля 2011

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

Я бы хотел избежать квадратной сложности. Существуют ли какие-либо общеизвестные способы уменьшения количества вызовов при обнаружении столкновений между объектами. Существуют ли какие-либо структуры данных (например, дерево BSP), которые легко поддерживаются и позволяют отклонять множество коллизий одновременно.

Например, общее количество объектов на уровне около 500, около 50 из них видны на экране одновременно ...

Спасибо!

Ответы [ 3 ]

9 голосов
/ 04 февраля 2011

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

Это будет стоить практически ничего.

4 голосов
/ 04 февраля 2011

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

См. Эту статью - Демонстрация квадродерева.

И, возможно, это - Обнаружение столкновения в двух измерениях.

Или это - Quadtree (включая источник)

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

0 голосов
/ 04 февраля 2011

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

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

...