Событие collide: подписка и данные контакта

Библиотека Cannon.js предоставляет мощный инструментарий для симуляции физики в браузере, включая обработку столкновений объектов. Одним из ключевых механизмов является событие collide, которое позволяет реагировать на контакт тел в реальном времени.


Подписка на событие collide

Событие collide генерируется объектами типа Body. Подписка осуществляется с использованием метода addEventListener или альтернативного синтаксиса on. Основная сигнатура выглядит следующим образом:

body.addEventListener('collide', function(event) {
    console.log(event);
});

Основные моменты:

  • Событие вызывается только тогда, когда тело участвует в столкновении.
  • Подписка работает для каждого конкретного тела, и каждое столкновение с другим объектом вызывает событие отдельно.
  • Можно использовать removeEventListener для удаления подписки.
function handleCollision(event) {
    console.log(event.contact);
}
body.removeEventListener('collide', handleCollision);

Структура объекта события

Объект события, передаваемый обработчику, содержит ключевую информацию о столкновении. Основные свойства:

  1. body — объект типа Body, с которым произошло столкновение.
  2. target — тело, на котором зарегистрирован слушатель (body текущего контекста).
  3. contact — объект контакта, содержащий сведения о точке и нормали столкновения.
  4. impactVelocity — относительная скорость тел в точке контакта.

Пример доступа к данным контакта:

body.addEventListener('collide', function(event) {
    const otherBody = event.body;
    const contact = event.contact;
    const impactVelocity = event.contact.getImpactVelocityAlongNormal();

    console.log('Столкновение с:', otherBody.id);
    console.log('Скорость удара:', impactVelocity);
    console.log('Точка контакта:', contact.ri, contact.rj);
});

Объект ContactEquation

Контакт между телами описывается через ContactEquation. Основные свойства и методы:

  • ni — нормаль контакта, направленная от тела i к телу j.
  • ri, rj — радиус-векторы точек контакта относительно центров масс тел i и j.
  • getImpactVelocityAlongNormal() — вычисляет скорость сближения тел по нормали контакта.
  • bi, bj — ссылки на тела, участвующие в контакте.

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

body.addEventListener('collide', function(event) {
    const contact = event.contact;
    console.log('Нормаль контакта:', contact.ni);
    console.log('Локальная точка на теле i:', contact.ri);
    console.log('Локальная точка на теле j:', contact.rj);
});

Практические сценарии применения

  1. Звуковые эффекты столкновений На основе impactVelocity можно варьировать громкость или тип звука удара.

  2. Визуальные эффекты Создание вспышек, искр или частиц в точке контакта с координатами ri и rj.

  3. Физическая реакция на столкновение Применение дополнительных сил или импульсов при контакте с определёнными объектами.

  4. Игровая логика Учет столкновений для подсчета очков, срабатывания триггеров или разрушения объектов.


Особенности работы

  • Событие collide вызывается только при активной симуляции физического мира (world.step()).
  • Если тела неподвижны или не пересекаются по времени шага, событие не срабатывает.
  • Для сложных объектов с несколькими формами (CompoundShape) событие будет генерироваться для каждой пары столкнувшихся форм.
  • Значения impactVelocity и координаты ri, rj зависят от масштаба времени симуляции, поэтому при высоких timeStep возможна потеря точности.

Рекомендации по оптимизации

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

Эта система событий в Cannon.js обеспечивает точный контроль над физикой столкновений и позволяет строить интерактивные и динамичные приложения с реалистичными реакциями объектов.