Новые возможности: TypeScript, улучшенный Spring, исправления

Cannon.js изначально разрабатывался на чистом JavaScript, однако с ростом популярности TypeScript библиотека получила поддержку типов через отдельные декларации. Для работы с TypeScript необходимо установить пакет типов @types/cannon или использовать современные форки с встроенной поддержкой типов.

Пример инициализации мира физики:

import * as CANNON from 'cannon';

const world = new CANNON.World();
world.gravity.set(0, -9.82, 0); // стандартная гравитация
world.broadphase = new CANNON.NaiveBroadphase();
world.solver.iterations = 10;

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


Работа с телами и формами

Создание тела включает определение массы, формы и материала:

const sphereShape = new CANNON.Sphere(1); // радиус 1
const sphereBody = new CANNON.Body({
    mass: 5,
    position: new CANNON.Vec3(0, 10, 0),
    shape: sphereShape
});
world.addBody(sphereBody);

Для сложных объектов можно комбинировать несколько форм в одном теле с помощью addShape:

const boxShape = new CANNON.Box(new CANNON.Vec3(1, 1, 1));
sphereBody.addShape(boxShape, new CANNON.Vec3(0, 2, 0));

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


Улучшенный Spring

В последних версиях Cannon.js существенно улучшена реализация пружин (Spring). Новые возможности позволяют задавать коэффициенты демпфирования, линейной и крутильной жесткости, а также привязывать пружину к телам с учётом их локальных точек.

Пример создания пружины:

const spring = new CANNON.Spring(sphereBody, boxBody, {
    localAnchorA: new CANNON.Vec3(0, -1, 0),
    localAnchorB: new CANNON.Vec3(0, 1, 0),
    restLength: 2,
    stiffness: 100,
    damping: 5
});

world.addEventListener('postStep', () => {
    spring.applyForce();
});
  • stiffness определяет силу возвращения к исходной длине.
  • damping отвечает за затухание колебаний, предотвращая «прыжки» объектов.
  • restLength задаёт естественную длину пружины, к которой стремится система.

Улучшенная версия Spring учитывает инерцию и вращение тел, что делает симуляцию более реалистичной, особенно для динамичных взаимодействий.


Исправления и стабильность

В последних обновлениях библиотеки были устранены ключевые проблемы:

  1. Корректное пересечение коллайдеров — прежние версии иногда позволяли объектам «проскальзывать» сквозь друг друга при высокой скорости. Исправление broadphase и solver уменьшает этот эффект.
  2. Обработка массивов тел — оптимизация добавления и удаления тел позволяет избежать утечек памяти при динамических сценах.
  3. Стабильность solver — улучшен итерационный процесс, что повышает точность расчёта столкновений и уменьшает артефакты при сложных системах, включая многозвенные цепочки.
  4. Фикс работы пружин при нулевой массе одного из тел — ранее это приводило к NaN в позициях и ориентациях.

Пример полной симуляции с TypeScript

const world = new CANNON.World();
world.gravity.set(0, -9.82, 0);

const ground = new CANNON.Body({
    mass: 0,
    shape: new CANNON.Plane(),
});
ground.quaternion.setFromEuler(-Math.PI/2, 0, 0);
world.addBody(ground);

const sphere = new CANNON.Body({
    mass: 1,
    shape: new CANNON.Sphere(1),
    position: new CANNON.Vec3(0, 10, 0)
});
world.addBody(sphere);

const box = new CANNON.Body({
    mass: 2,
    shape: new CANNON.Box(new CANNON.Vec3(1,1,1)),
    position: new CANNON.Vec3(2,15,0)
});
world.addBody(box);

const spring = new CANNON.Spring(sphere, box, {
    restLength: 5,
    stiffness: 50,
    damping: 2
});

function simulate(dt: number) {
    world.step(dt);
    spring.applyForce();
}

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


Рекомендации по использованию новых возможностей

  • Для сложных проектов использовать TypeScript обязательно, чтобы исключить ошибки типов.
  • Spring теперь можно применять не только для линейных связей, но и для гибких конструкций с множеством тел.
  • При высоких скоростях объектов активировать solver.iterations ≥ 10 и использовать NaiveBroadphase только для небольших сцен.
  • Проверять взаимодействие тел с нулевой массой, так как некоторые методы (applyImpulse) изменены для стабильности.

Cannon.js с TypeScript и улучшенной системой пружин становится удобным инструментом для реализации реалистичных физических симуляций в браузере, сочетая точность расчётов и гибкость API.