О чем этот пример

Создание плавной, непрерывной анимации — основа визуального комфорта в играх. Ключевая проблема — заставить объекты двигаться с одинаковой скоростью на любых устройствах, независимо от частоты кадров. В этом примере из официальной коллекции Phaser показан элегантный паттерн для бесконечного скроллинга фонового элемента с использованием дельты времени (`delta`). Мы разберем, как это работает и почему это важно для производительности.

Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.

Живой запуск

Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.

Исходный код


class SceneD extends Phaser.Scene {

    constructor ()
    {
        super('SceneD');

        this.planet;
    }

    create ()
    {
        this.cameras.main.setViewport(0, 136, 1024, 465);

        this.planet = this.add.image(200, 380, 'space', 'planet');
    }

    update (time, delta)
    {
        this.planet.x += 0.01 * delta;

        if (this.planet.x >= 1224)
        {
            this.planet.x = -200;
        }
    }

}

Инициализация сцены и объявление переменной

Класс сцены наследуется от Phaser.Scene. В конструкторе мы задаём системный ключ сцены и заранее объявляем переменную для нашего игрового объекта. Это хорошая практика для организации кода и дальнейшего доступа к объекту из других методов класса.

class SceneD extends Phaser.Scene {
    constructor ()
    {
        super('SceneD');
        this.planet;
    }

Создание объектов и настройка камеры

Метод create() выполняется один раз при запуске сцены. Здесь мы задаём область просмотра (viewport) для основной камеры, позиционируя её в нужной части экрана. Затем создаём спрайт планеты, используя текстуру 'space' и конкретный кадр 'planet' из атласа. Позиция (200, 380) задаёт начальные координаты центра изображения.

create ()
{
    this.cameras.main.setViewport(0, 136, 1024, 465);
    this.planet = this.add.image(200, 380, 'space', 'planet');
}

Сердце анимации: метод update и delta

Метод update() вызывается на каждом кадре игры. Параметр delta — это ключевая величина. Он представляет время, прошедшее с предыдущего кадра, в миллисекундах. Умножая скорость на delta, мы привязываем движение не к количеству кадров, а к реальному времени. Это гарантирует, что планета будет перемещаться на 10 пикселей в секунду (0.01 * 1000ms = 10px/s) всегда, вне зависимости от FPS.

update (time, delta)
{
    this.planet.x += 0.01 * delta;
}

Реализация бесконечного цикла (wrap-around)

Чтобы создать эффект бесконечного движения, мы отслеживаем позицию объекта. Когда координата `x` планеты превышает правую границу экрана (с учётом её ширины и начальной позиции), мы мгновенно перемещаем её за левую границу. Это создаёт иллюзию непрерывного космического фона.

if (this.planet.x >= 1224)
    {
        this.planet.x = -200;
    }
}

Что попробовать дальше

Использование delta в update() — это фундаментальный паттерн для платформонезависимой анимации в Phaser. Для экспериментов попробуйте изменить константу 0.01, чтобы варьировать скорость. Добавьте вторую планету с другой скоростью для эффекта параллакса. Или замените простой перенос на плавное изменение через tweens для более сложных траекторий.