Якщо взаємодіють два об'єкти, що містить код взаємодії?


28

Придумайте кулю і ворога, або гравця та підлогу. Якщо ці об'єкти взаємодіють, у чому полягає код взаємодії?


2
Яким чином взаємодіяти? Ви маєте на увазі виявлення зіткнення? Якщо так, то, швидше за все, ви будете реалізовувати як клас виявлення зіткнень, так і менеджер розв'язання зіткнень.
CaptainRedmuff

Частково так, мене цікавить і зіткнення, і те, що станеться після зіткнення. Чи перевіряє куля, чи вона близька до ворога, чи навпаки? А що станеться після зіткнення, чи може кульовий предмет просто повідомити ворогу, що його вдарили? Як ви бачите, я досить розгублений у всьому, і це робить дуже важким для читання код.
ThatOneGuy

Відповіді:


23

TL; DR:

Ваші ігрові об’єкти не знають один про одного, а також не перевіряють інші об'єкти. Ви створюєте схему виявлення зіткнення та розв'язання зіткнення, яка перевіряє ваші ігрові об’єкти та виконує відповідні дії для імітації фізики вашої гри.

Хороші речі

З попередніх спроб написання виявлення зіткнення та читання цієї книги є два етапи виявлення зіткнення та вирішення зіткнення. Перший етап (виявлення зіткнення) - це ранній прохід, де ви визначаєте, чи можуть два об'єкти мати потенційне зіткнення. Якщо будь-які два об'єкти утворюють потенційне зіткнення, ви передаєте ці об'єкти на другу стадію (дозвіл зіткнення), щоб здійснити більш дрібну перевірку об'єктів та спробувати вирішити зіткнення.

Десь у вашому двигуні / грі ви будете тримати масив усіх об’єктів у вашому світі. На кожному кадрі ви будете циклічно розміщувати масив і перевіряти кожен об'єкт проти кожного іншого об'єкта за допомогою простого виявлення обмеження поля / сфери зіткнення.

Псевдокод:

dectectCollisions(objects)
{
    for(objectA in objects)
    {
        for(objectB in objects)
        {
            if(objectA != objectB) //ignore self
            {
                if(BoundingSpheresIntersect(objectA, objectB))
                {
                    collisionResolver.addObjects(objectA, objectB);
                }
            }
        }
    }
}

Цей тип циклу є досить неефективним, але залишає місце для вдосконалення за допомогою використання просторового розподілу як раннього для об'єктів, які гарантовано знаходяться занадто далеко один від одного, щоб зіткнутися.

Після перевірки двох об'єктів на потенційне зіткнення (тобто обидва об'єкти є досить близькими для зіткнення), об'єкти передаються для виконання більш точної процедури виявлення зіткнення.

Уявіть, що у вас є два багатокутники випадкових форм і розмірів, які досить близькі, щоб потенційно перетинатися, але не обумовлені їх геометрією:

Зображення знайдено через google

Використовуючи обмежуючі сфери, ці два об'єкти створили б помилковий позитив для потенційного зіткнення. Тут ви б виконали більш ретельний прохід, щоб визначити, чи справді два об'єкти перетинаються.

Після того, як ви знайшли справжнє зіткнення, ваш крок вирішення зіткнення буде виконувати відповідні дії для вирішення об'єктів, застосовуючи сили або моменти залежно від деталізації та потреб фізики вашої гри.

Зважаючи на це, ви можете абстрагувати весь процес виявлення та вирішення зіткнень, щоб ваші об'єкти нічого не знали один про одного, а також процес, необхідний для визначення та вирішення зіткнень. Двум класам / менеджерам, які займаються цим, потрібно лише знати основні властивості кожного об'єкта для швидкої та брудної перевірки на зіткнення, а потім, якщо це буде потрібно, більш ретельна перевірка.


2
Зокрема, модель дизайну Mediator була б доречною. Модель спостерігача була б хорошою альтернативою, яка має зовсім інший намір. Ви можете отримати досить хороший підсумок їх у цій публікації про Stackoverflow .
kurtzbot

12

Один із способів Unreal Engine 3 обробляє це:

Куля отримує повідомлення про зіткнення, в якому йдеться про те, що воно щось вдарило, аргумент - це те, що вдарило. Потім він може викликати objectHit.takeDamage (self). Потім ціль отримує повідомлення TakeDamage із вказівником на річ, яка потрапила в нього, і вживає відповідних дій.

Мені особисто подобається такий підхід, оскільки це означає, що куля може вчинити спеціальні дії (наприклад, робити якийсь ефект вибуху залежно від типу удару), а ціль може вживати спеціальних дій залежно від типу кулі.

Можливо також, що куля знає, що робить для цілей, і може викликати функцію на ній, наприклад objectHit.freeze (self). Тоді ціль знає, що в неї потрапило щось, що заморожує її, і який саме предмет був.

EDIT: Ця відповідь розуміється як загальна картина того, як вона може працювати, оскільки ви, ймовірно, не працюєте з UE3. :)


10

Злодій зробив це дуже добре в Темному двигуні з джерелами та рецепторами. Об'єкт може мати обидва ці властивості, з різними типами. Наприклад, стрілка для води матиме джерело для WaterStim при контакті. Вибух мав би AoE FireStim.

Коли Водна стрілка потрапляє на об’єкт, цільовий об’єкт потім шукає свої рецептори для того, щоб шукати WaterStim з відповідними значеннями інтенсивності. Потім він виконує будь-яку команду, пов’язану з ним (у цьому випадку, перетворюючи палаючий пальник на вимкнутий факел, і видає дим.)

Оскільки в SystemShock2 використовується один і той же двигун, таким чином обробляються всі різні типи пошкоджень, різні кулі мають різний набір Stims, а різні монстри мають Receptrons для різних типів Stim і завдають шкоди рівній 1 *, 2 *, 1 / 2 інтенсивність залежно від того, тип боєприпасу є "суперефективним" чи ні.

Здавалося, це дуже гнучка система, оскільки ви можете додавати джерела та рецептори до об'єктів у редакторі рівнів (щоб зробити одноразову двері, яка відкриється, якщо потрапить вогонь, скажімо.) Хоча ви також можете сказати рецептору, щоб "відправити скрипт повідомлення ", якщо об'єкт мав спеціальні сценарії, пов'язані з ним.

Що ви не хочете робити - це жорсткий код матриці взаємодії nXn усіх можливих об'єктів, що стикаються з усіма можливими об'єктами! Шляхом узагальнення взаємодій за допомогою стандартизованих повідомлень ви спрощуєте процес.


З точки зору сценаріїв, цей підхід видається найбільш гнучким та найвиразнішим. Дуже круто.
drhayes

-2

Одне рішення - тримати контейнери з куль і гравців в окремих класах, а потім мати функцію main (), яка підтримує цикл кадру, відповідальний за взаємодію.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.