В Cannon.js управление симуляцией происходит через объект
World. Для реализации паузы часто используют механизм
контроля времени обновления мира. Основная идея заключается в том, чтобы
при приостановке симуляции не вызывать метод
step или вызывать его с нулевым временем.
Пример реализации паузы:
let isPaused = false;
function animate() {
requestAnimationFrame(animate);
if (!isPaused) {
world.step(timeStep);
}
// рендеринг сцены
renderer.render(scene, camera);
}
Ключевой момент — условие проверки isPaused
перед шагом мира. При true физика не обновляется,
но графическая сцена может продолжать рендериться, что позволяет
сохранять визуальную интерактивность интерфейса.
Для более точного управления временем можно использовать
динамический deltaTime, который передается
в step. Это полезно при реализации перемотки или медленного
воспроизведения:
world.step(timeStep, deltaTime, maxSubSteps);
timeStep — фиксированный шаг симуляции (например,
1/60).deltaTime — фактическое прошедшее время с прошлого
кадра.maxSubSteps — максимальное число шагов за один кадр для
предотвращения пропусков.Иногда требуется полностью очистить физический мир, чтобы начать
симуляцию заново. Cannon.js не имеет встроенного метода
reset, поэтому процесс осуществляется вручную. Основные
шаги:
world.bodies.forEach(body => {
world.removeBody(body);
});
world.constraints.forEach(constraint => {
world.removeConstraint(constraint);
});
world.contacts.length = 0;
world.accumulators.forEach(acc => acc.clear());
gravity, solver.iterations,
broadphase можно оставить или переопределить:world.gravity.set(0, -9.82, 0);
world.solver.iterations = 10;
Полный сброс гарантирует отсутствие артефактов старой симуляции и позволяет безопасно пересоздавать объекты.
Пересоздание мира часто используется при изменении основных параметров симуляции, например при смене размеров объектов или изменении физического движка (solver, broadphase). Создание нового мира происходит следующим образом:
world = new CANNON.World();
world.gravity.set(0, -9.82, 0);
world.broadphase = new CANNON.NaiveBroadphase();
world.solver.iterations = 10;
После создания нового объекта мира необходимо заново добавлять тела, материалы и ограничения. Материалы и контакты также требуют пересоздания, так как привязаны к конкретному миру.
const material = new CANNON.Material("default");
const sphereBody = new CANNON.Body({
mass: 5,
shape: new CANNON.Sphere(1),
material: material
});
world.addBody(sphereBody);
Body, Constraint и
Material становятся недействительными в новом мире. Их
необходимо создавать заново.gravity, solver, broadphase
задаются заново, иначе используются значения по умолчанию.postStep,
beginContact, если они использовались.Эффективное управление паузой, сбросом и пересозданием мира позволяет создавать гибкие и надежные симуляции, обеспечивая контроль над каждым аспектом физической сцены и предотвращая накопление ошибок в динамических вычислениях.