В библиотеке Cannon.js кинематические тела представляют собой объекты, движение которых управляется напрямую через код, а не через физические силы. Они используются для создания платформ, лифтов, дверей, объектов с заранее заданной анимацией, при этом не подвергаясь воздействию силы тяжести, столкновений или трения в обычном смысле.
Кинематические тела создаются аналогично динамическим, но их
тип тела задается как Body.KINEMATIC.
Например:
const body = new CANNON.Body({
mass: 0, // масса не влияет на движение
type: CANNON.Body.KINEMATIC,
shape: new CANNON.Box(new CANNON.Vec3(1, 1, 1))
});
Ключевой особенностью кинематических тел является явное
задание позиции и ориентации. Cannon.js не рассчитывает их
движение на основе сил и импульсов. Вместо этого положение обновляется
напрямую через свойства position и
quaternion.
body.position.set(0, 5, 0);
body.quaternion.setFromEuler(0, Math.PI/4, 0);
Для анимации кинематических объектов обычно используется функция обновления в цикле рендеринга:
function updateKinematicBody(deltaTime) {
body.position.x += 2 * deltaTime; // постоянная скорость по оси X
body.quaternion.setFromEuler(0, performance.now() / 1000, 0); // вращение
}
deltaTime — это время, прошедшее с предыдущего кадра,
что позволяет движение оставлять независимым от частоты
кадров.
Если кинематическое тело сталкивается с динамическими объектами, Cannon.js корректно обрабатывает столкновения: динамическое тело отталкивается, а кинематическое продолжает движение по заданной траектории.
Body.STATIC) –
неподвижны, взаимодействуют с динамическими объектами, но не
двигаются.Body.KINEMATIC) –
двигаются по заданной траектории, воздействуют на динамические объекты,
но не подчиняются физическим силам.Body.DYNAMIC) –
полностью управляются физикой: силами, импульсами и столкновениями.При взаимодействии с динамическими объектами Cannon.js использует алгоритм импульсов для корректного отталкивания. Важно помнить:
body.addEventListener('collide', function(event) {
const other = event.body;
console.log('Столкновение с', other.id);
});
Для плавного движения кинематического объекта можно использовать интерполяцию:
const startPos = new CANNON.Vec3(0, 0, 0);
const endPos = new CANNON.Vec3(10, 0, 0);
const duration = 5; // секунд
let elapsed = 0;
function animate(deltaTime) {
elapsed += deltaTime;
const t = Math.min(elapsed / duration, 1);
body.position.lerp(startPos, endPos, t);
}
Метод lerp обеспечивает линейное перемещение между двумя
точками, что особенно полезно для платформ или объектов с заранее
заданной анимацией.
Для поворота объектов используются кватернионы или преобразования Эйлера. Прямое изменение углов Эйлера:
body.quaternion.setFromEuler(0, Math.PI * Math.sin(performance.now()/1000), 0);
Для сложной анимации можно комбинировать slerp для
плавного вращения между кватернионами:
const q1 = new CANNON.Quaternion();
const q2 = new CANNON.Quaternion();
q2.setFromEuler(0, Math.PI/2, 0);
CANNON.Quaternion.slerp(q1, q2, body.quaternion, 0.05);
slerp обеспечивает плавное вращение без резких скачков и
сохраняет нормализацию кватерниона.
В большинстве проектов обновление кинематических тел выполняется в основном цикле симуляции:
world.step(timeStep);
updateKinematicBody(timeStep);
renderer.render(scene, camera);
Важно, чтобы обновление положения и ориентации происходило до шага физического мира, иначе динамические объекты могут получить некорректные столкновения.
Кинематические объекты позволяют создавать сложные интерактивные сцены, где физические взаимодействия сохраняются, но движение задается программно.
position и quaternion.sleep или отключение столкновений для
объектов, которые временно не участвуют в физике, чтобы снизить нагрузку
на расчёт коллизий.Эффективное использование кинематических тел позволяет создавать реалистичную анимацию объектов и сложные игровые механики, сохраняя при этом корректное взаимодействие с динамическими частями сцены.