Где должна быть размещена логика обнаружения столкновений?

19

Я занимаюсь разработкой небольшого 2D игрового движка. У персонажей есть метод рисования, который в настоящее время делает следующее:

  1. Рассчитать новую позицию персонажа по скорости и т. Д.
  2. Обновить ячейку сетки столкновений **
  3. Нарисуйте персонажа на новой позиции

** Я создал сетку столкновений, чтобы уменьшить количество проверок пересечения

Теперь основной алгоритм, который я подумал для обнаружения столкновения:

For Each Character
    Check intersection with characters in surrounding 8 cells

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

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

Но у меня есть идея, что, когда A обнаруживает, что он столкнулся с B, он должен сообщить B, что он столкнулся с A. Это спасло бы много сравнений, когда сталкиваются более двух действующих лиц. Но я не уверен, как справиться с этим. Я думаю, что вместо каждого персонажа, проверяющего его столкновение, я должен проверять наличие столкновения внутри игрового цикла.

Будет ли этот подход правильным? Как вы справились с такой проблемой? Я сам думал о решетке столкновений. Есть ли альтернативы логике коллизионной сетки?

крекер
источник
Прошу прощения за придирки, но в специализированной 2D библиотеке физики. Физика игры обычно очень приблизительна, поэтому любое решение, которое не делает игру неиграемой, подойдет, но если вы хотите решить ее правильно, просто используйте специализированную физику, такую ​​как Box2D ... :-D
user712092

Ответы:

14

Обычный подход для обнаружения столкновений состоит в том, чтобы не иметь ни A, ни B самостоятельно обнаруживать столкновения.

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

Таким образом, по сути, вместо того, чтобы выполнять «перемещение, проверку на столкновение, рисование» внутри функции Paint (), вы разделяете «перемещение» и «рисование» на отдельные функции, которые вы вызываете отдельно (сначала «перемещение» для каждого объекта, затем «рисовать» для каждого объекта). И между этими, проверьте на столкновения.

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

Тревор Пауэлл
источник
Это правильный способ делать вещи. Пусть объекты справляются со своими обязанностями, а система столкновений должна решать, что происходит, когда они встречают препятствие. Вы также можете иметь прямоугольник / цилиндр столкновения (2d / 3d) вокруг ваших персонажей как своего рода ранний триггер.
Джеймс П.
Большой! Что касается расширенного примечания, не следует ли перепроверять столкновения только для объектов, которые перемещаются в ответ на столкновение, и объектов, с которыми они сталкиваются в новой позиции? Будет цепочка проверок, но это позволит избежать проверки столкновения для всех объектов.
Взломщик
Как с этим справиться - gamedev.stackexchange.com/questions/13076/…
Взломщик
1

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

Я делаю это с состоянием каждого из моих персонажей, поэтому, если A и B сталкиваются, когда A проверяет столкновение, A и B устанавливаются на попадание. в начале цикла B он проверяет, ударил ли он, если так, то id не запускает цикл.

Я поместил код аффекта в цикл, чтобы любое действие, которое должно быть выполнено с B, происходило в цикле A, поэтому у B не должно быть оснований для проверки, так как это может испортить исход столкновения, хотя для вас это может отличаться ,

Skeith
источник
Но в этом случае, когда A обнаруживает пересечение с B, B.hit будет установлен в true, и поэтому B не будет проверять ЛЮБОЕ пересечение. Но если другой символ C пересекается с B, B не обнаружит это?
Взломщик
Извини, понял. Поскольку A не пересекается с C, C.hit все равно будет ложным. B не будет проверять наличие столкновений. Но C проверит и передаст информацию B, что между B и C. произошла коллизия. Круто!
Взломщик
Но я думаю, что если бы все А, В и С пересекались друг с другом, возникла бы проблема. A установит для B.hit и C.hit значение true. B и C будут знать, что они столкнулись с A. Но поскольку их свойство попадания истинно, они не будут проверять наличие столкновения. Столкновение В и С останется незамеченным.
Взломщик
Вы можете прокрасться подобным способом, поместив каждый жизнеспособный объект столкновения в какую-либо коллекцию, затем проверяя только столкновение с вещами, которые идут после объекта в коллекции. IE: A проверяет против B, C, D; B проверяет против C, D; С проверяет против D. Каждого позади не нужно проверять, так как он уже проверен с очереди того, кто позади. Не так быстро, как полное исключение столкновения элемента, но, тем не менее, полезно.
Лунин