Де слід розмістити логіку виявлення зіткнень?


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/…
Cracker

1

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

Так, як я це роблю, є стан кожного з моїх персонажів, тому якщо A і B стикаються, коли A перевіряє зіткнення, A і B встановлюються на удар. на початку циклу B він перевіряє, чи вже він потрапив, якщо так, id не запускає цикл.

Я поміщаю код впливу в цикл, щоб будь-які дії, які слід здійснити на B, траплялися в циклі A, тому не повинно бути причин B перевіряти, оскільки це зіпсує результат зіткнення, для вас це може бути інакше .


Але в цьому випадку, коли A виявить перехрестя з B, B.hit буде встановлено на істинне, і тому B не перевірить БІЛЬКЕ перехрестя. Але якщо інший символ C перетинається з B, B не виявить його?
Крекер

Вибачте, зрозумів. Оскільки A не перетинається з C, C.hit все одно буде помилковим. Б не перевірять на зіткнення. Але C перевірить і передасть інформацію B, що між B і C. сталося зіткнення. Класно!
Крекер

Але я здогадуюсь, якщо всі A, B і C перетинаються між собою, виникла б проблема. А встановить B.hit і C.hit на істину. B і C будуть знати, що вони зіткнулися з A. Але, оскільки їх властивість ураження справжня, вони не перевірять на зіткнення. Зіткнення між В і С залишиться непоміченим.
Крекер

Ви можете прокрастись аналогічним методом, помістивши кожен життєздатний об'єкт зіткнення у якусь колекцію, а потім лише перевірити зіткнення з речами, що надходять після об'єкта в колекції. IE: А перевірки проти B, C, D; B перевірки проти C, D; C перевіряє проти D. Кожного ззаду не потрібно перевіряти, оскільки це вже було відмічено від черги позаду. Не так швидко, як цілком пропускати зіткнення стихії, але все-таки корисно.
Лунін
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.