В библиотеке Phaser управление частотой кадров
является ключевым аспектом для стабильной работы игр и точного расчёта
физики. Частота кадров (FPS, Frames Per Second) определяет, сколько раз
в секунду вызываются методы рендеринга и обновления сцены. Phaser по
умолчанию стремится максимально использовать ресурсы устройства, вызывая
метод update столько раз, сколько позволяет браузер. Это
может привести к нестабильной скорости игры на разных устройствах.
При создании экземпляра игры используется объект конфигурации, где задаются параметры рендеринга и частоты кадров:
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
scene: {
preload: preload,
create: create,
update: update
},
fps: {
target: 60,
forceSetTimeOut: false
}
};
const game = new Phaser.Game(config);
Ключевые параметры объекта fps:
target — желаемое количество кадров в секунду. Обычно
это 60 для плавной анимации.forceSetTimeOut — при true используется
setTimeout вместо requestAnimationFrame, что
может быть полезно для совместимости, но снижает плавность.Phaser предоставляет встроенный объект this.game.loop,
который содержит текущую статистику FPS:
console.log(this.game.loop.actualFps); // реальная частота кадров
console.log(this.game.loop.delta); // время между кадрами в миллисекундах
actualFps показывает реальную частоту кадров, которая
может отличаться от target из-за нагрузки.delta позволяет адаптировать движение объектов к
изменяющейся частоте кадров, чтобы скорость была одинаковой на медленных
и быстрых устройствах.Использование фиксированного шага в методе update
необходимо для корректной работы физики и предсказуемой
анимации. При переменной частоте кадров объекты движутся неравномерно, и
расчёт столкновений может дать ошибки.
Идея фиксированного шага заключается в том, что логика игры обновляется через равные интервалы времени, независимо от FPS:
const FIXED_STEP = 1 / 60; // 60 обновлений в секунду
let accumulator = 0;
function update(time, delta) {
accumulator += delta / 1000; // преобразование миллисекунд в секунды
while (accumulator >= FIXED_STEP) {
fixedUpdate(FIXED_STEP);
accumulator -= FIXED_STEP;
}
}
accumulator хранит накопленное время между
кадрами.fixedUpdate выполняет физические расчёты или движения с
одинаковым шагом времени.Phaser поддерживает Arcade Physics, которая сама
использует фиксированный шаг по умолчанию. Однако при ручной реализации
поведения объектов можно применять собственный
fixedUpdate:
function fixedUpdate(step) {
player.x += player.vx * step;
player.y += player.vy * step;
// проверка столкновений
this.physics.world.collide(player, platforms);
}
Использование фиксированного шага гарантирует одинаковую скорость движения объектов на экранах с разной частотой обновления.
В некоторых случаях удобно комбинировать delta-time с фиксированным шагом. Это позволяет адаптировать анимации к FPS, сохраняя стабильную физику:
function update(time, delta) {
// переменные для анимации
sprite.x += sprite.vx * (delta / 1000);
// фиксированная логика
accumulator += delta / 1000;
while (accumulator >= FIXED_STEP) {
fixedUpdate(FIXED_STEP);
accumulator -= FIXED_STEP;
}
}
delta, что делает анимацию плавной.requestAnimationFrame.actualFps позволяет выявлять узкие места
производительности и корректировать нагрузку.Фиксированный шаг в сочетании с контролем частоты кадров обеспечивает предсказуемое поведение игры и стабильность симуляции на любых устройствах.