ContactCallback: подписка на события контакта

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


Основы ContactCallback

ContactCallback представляет собой объект, который регистрируется в мире (OIMO.World) и получает уведомления о событиях контакта двух тел. События могут быть нескольких типов:

  • begin – возникает в момент первого касания двух тел.
  • end – возникает, когда контакт прекращается.
  • persist – возникает на каждом шаге симуляции, пока два тела находятся в контакте.

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


Создание и регистрация ContactCallback

Создание колбэка требует определения объекта с методами для нужных событий. Пример базового синтаксиса:

const callback = new OIMO.ContactCallback();

callback.begin = function(contact) {
    console.log('Начало контакта между', contact.body1.name, 'и', contact.body2.name);
};

callback.end = function(contact) {
    console.log('Контакт завершён между', contact.body1.name, 'и', contact.body2.name);
};

callback.persist = function(contact) {
    console.log('Контакт продолжается между', contact.body1.name, 'и', contact.body2.name);
};

// Регистрация в мире
world.registerContactCallback(callback);

Здесь contact — объект класса OIMO.Contact, содержащий информацию о столкновении:

  • body1 и body2 – участвующие в контакте тела.
  • shape1 и shape2 – формы тел, участвующие в столкновении.
  • manifold – информация о точках контакта, нормалях и глубине проникновения.

Структура объекта Contact

Объект Contact предоставляет детализированную информацию для точного контроля:

contact.body1.position; // Позиция первого тела
contact.body2.velocity; // Скорость второго тела
contact.manifold.points; // Массив точек контакта
contact.manifold.normal; // Нормаль контакта
contact.manifold.depth;  // Глубина проникновения

Использование этих данных позволяет реализовать:

  • Проверку силы удара и динамическое реагирование на неё.
  • Создание эффектов от столкновения, таких как отскок или деформация.
  • Применение физических эффектов, например, трения или упругости, к отдельным точкам контакта.

Фильтрация контактов

В сложных симуляциях часто необходимо отслеживать контакты только для определённых объектов. Для этого можно использовать фильтры на основе имени тела или метки:

callback.begin = function(contact) {
    if(contact.body1.name === 'Player' && contact.body2.name === 'Enemy') {
        console.log('Игрок столкнулся с врагом');
    }
};

Такой подход предотвращает лишние вычисления и делает обработку событий более эффективной.


Практические сценарии использования

  1. Триггерные зоны Обычное применение ContactCallback — определение, когда объект входит в зону активации:

    callback.begin = function(contact) {
        if(contact.body1.name === 'Player' && contact.body2.name === 'Checkpoint') {
            console.log('Игрок достиг контрольной точки');
        }
    };
  2. Урон при столкновении Используя contact.manifold.depth и contact.body.velocity, можно вычислять силу удара:

    const impact = contact.manifold.depth * contact.body2.velocity.length();
    if(impact > 5) {
        console.log('Сильный удар! Нанесён урон');
    }
  3. Эффекты столкновения Для визуальных эффектов можно создавать частицы или анимацию в точках контакта:

    contact.manifold.points.forEach(point => {
        spawnParticles(point);
    });

Оптимизация производительности

  • Подписка на persist для всех тел может быть затратной. Лучше ограничивать её только ключевыми объектами.
  • Использование фильтров на уровне begin и end уменьшает количество ненужных вычислений.
  • Избегать сложных операций внутри колбэков, особенно алгебраических или DOM-манипуляций, чтобы не тормозить физический шаг симуляции.

Взаимодействие с другими компонентами Oimo.js

ContactCallback тесно интегрирован с другими элементами библиотеки:

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

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


Расширенные возможности

  • Можно создавать несколько ContactCallback и регистрировать их для разных сценариев, что обеспечивает модульность кода.
  • Методы колбэка могут быть переопределены динамически, позволяя менять поведение в зависимости от состояния игры.
  • Доступ к manifold открывает возможность для кастомной физики на уровне точек контакта, например, для симуляции мягких тел или цепочек столкновений.

Использование ContactCallback в Oimo.js обеспечивает полный контроль над событиями контакта, позволяя гибко управлять физическими взаимодействиями, реагировать на столкновения и интегрировать физику с игровой логикой.