О чем этот пример
Каждый кадр вашей игры — это результат вычислений, и их точность критична для плавной анимации и отзывчивого геймплея. Phaser предоставляет простой доступ к глобальному времени игры и времени, прошедшему с предыдущего кадра. Понимание этих параметров — ключ к созданию независимых от частоты кадров анимаций, плавных перемещений и сложных таймингов.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
timeText;
create ()
{
this.timeText = this.add.text(100, 200);
}
update (time, delta)
{
this.timeText.setText(`Time: ${time}\nDelta: ${delta}`);
}
}
const config = {
type: Phaser.CANVAS,
width: 800,
height: 600,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Зачем нужны `time` и `delta`?
В идеальном мире игры работают с постоянной частотой кадров. В реальности же FPS может «плавать» из-за сложности сцены или нагрузки на систему. Если привязывать скорость движения объекта напрямую к кадрам, в моменты просадки производительности игра начнёт «тормозить».
Phaser решает эту проблему, передавая в метод update два параметра: time и delta. Они позволяют делать расчёты, основанные на реальном прошедшем времени, а не на количестве кадров. Это называется «независимость от частоты кадров» (frame rate independence).
Глобальное время игры: параметр `time`
Параметр time — это количество миллисекунд, прошедших с момента запуска игры. Это монотонно возрастающее значение, своего рода внутренние часы движка.
Чаще всего time используется для расчётов, требующих абсолютной временной точки: триггеров событий по расписанию, анимаций по кривым или синусоидальных движений.
В нашем примере мы просто выводим это значение на экран.
update (time, delta)
{
// time содержит время в мс с момента старта игры
this.timeText.setText(`Time: ${time}`);
}
Время между кадрами: параметр `delta`
Параметр delta — это самое важное значение для создания плавного движения. Он показывает, сколько миллисекунд прошло с момента вызова предыдущего update.
В идеальных условиях при 60 FPS delta будет примерно равен 16.66 мс. Если игра начнёт тормозить и следующий кадр отрисуется через 50 мс, значение delta будет равно 50.
Используя delta, вы можете перемещать объект с постоянной скоростью в пикселях в секунду, независимо от FPS.
update (time, delta)
{
// Перемещаем спрайт со скоростью 100 пикселей в секунду
// delta в миллисекундах, поэтому делим на 1000
this.player.x += (100 * delta) / 1000;
}
Практическое применение: движение с постоянной скоростью
Вот как выглядит базовый шаблон для перемещения объекта. Скорость задаётся в пикселях в секунду, а delta обеспечивает корректное расстояние для перемещения за время между кадрами.
create ()
{
this.sprite = this.physics.add.image(100, 300, 'player');
// Скорость в пикселях в секунду
this.speed = 200;
}
update (time, delta)
{
// Пересчёт скорости с учётом дельты времени
const velocity = (this.speed * delta) / 1000;
this.sprite.x += velocity;
}
Этот подход гарантирует, что объект всегда пройдёт 200 пикселей за ровно одну секунду реального времени, даже если игра рендерится с разной частотой кадров.
Что попробовать дальше
Использование delta для всех расчётов, связанных со временем, — это фундаментальная практика в Phaser. Она делает вашу игру стабильной и предсказуемой на любом железе. Для экспериментов попробуйте создать метроном, который тикает раз в секунду, используя накопление значения delta, или анимируйте масштаб объекта по синусоиде, используя глобальное time для расчёта угла.
