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

Движущиеся фоны и повторяющиеся текстуры — частый элемент в играх. Phaser предлагает для этого мощный инструмент `TileSprite`. В отличие от обычного спрайта, тайловый спрайт позволяет бесшовно повторять текстуру, создавая эффект бесконечного скроллинга или анимированного фона. Эта статья покажет, как создавать тайловые спрайты, используя кадры из загруженного атласа, и управлять их движением, что полезно для создания параллакс-эффектов, анимированных задних планов или динамических UI-элементов.

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    iter = 0;
    images = [];

    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.atlas('atlas', 'assets/atlas/megaset-2.png', 'assets/atlas/megaset-2.json');
    }

    create ()
    {
        const frames = [ 'atari400', 'bunny', 'cokecan', 'copy-that-floppy', 'hotdog' ];
        for (let i = 0; i < frames.length; ++i)
        {
            this.images[i] = this.add.tileSprite(i * 160, 0, 160, 600, 'atlas', frames[i]);
            this.images[i].originX = 0;
            this.images[i].originY = 0;
        }
    }

    update ()
    {
        let x = 1;
        for (let i = 0; i < this.images.length; ++i)
        {
            this.images[i].tilePositionX += x;
            x *= -1;
        }
        this.iter += 0.01;
    }
}

const config = {
    type: Phaser.WEBGL,
    width: 800,
    height: 600,
    backgroundColor: '#2d2d2d',
    parent: 'phaser-example',
    scene: Example
};

const game = new Phaser.Game(config);

Загрузка ресурсов: подготовка атласа

Работа с тайловыми спрайтами начинается с загрузки текстур. В примере используется не отдельное изображение, а целый атлас — один PNG-файл, содержащий множество отдельных спрайтов, и JSON-файл с координатами каждого из них. Это оптимизирует производительность, сокращая количество HTTP-запросов.

В методе preload мы устанавливаем базовый URL для загрузки и загружаем сам атлас с помощью this.load.atlas. Методу передаются ключ для обращения к атласу, путь к изображению и путь к JSON-файлу с разметкой.

preload ()
{
    this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
    this.load.atlas('atlas', 'assets/atlas/megaset-2.png', 'assets/atlas/megaset-2.json');
}

Создание тайловых спрайтов

После загрузки в методе create мы создаем несколько тайловых спрайтов. Ключевой метод здесь — this.add.tileSprite. Он создает игровой объект, текстура которого будет повторяться (тайлиться) внутри заданных границ.

Мы перебираем массив с именами кадров (frames) из атласа. Для каждого кадра создается тайловый спрайт с указанием координат X, Y, ширины, высоты, ключа атласа и имени конкретного кадра из этого атласа.

Важный момент — смена точки отсчета (origin). По умолчанию она находится в центре объекта. Установка originX и originY в 0 смещает ее в левый верхний угол. Это упрощает позиционирование, особенно при выравнивании по сетке.

create ()
{
    const frames = [ 'atari400', 'bunny', 'cokecan', 'copy-that-floppy', 'hotdog' ];
    for (let i = 0; i < frames.length; ++i)
    {
        this.images[i] = this.add.tileSprite(i * 160, 0, 160, 600, 'atlas', frames[i]);
        this.images[i].originX = 0;
        this.images[i].originY = 0;
    }
}

Анимация через смещение тайла

Магия движения тайлового спрайта заключается в изменении его свойства tilePosition. В отличие от позиции самого игрового объекта на сцене, tilePosition определяет смещение внутренней текстуры. Изменяя его, мы создаем иллюзию движения текстуры внутри неподвижного контейнера.

В методе update, который вызывается каждый кадр, мы в цикле изменяем свойство tilePositionX каждого спрайта. Переменная `x` чередует свое значение между 1 и -1 для соседних спрайтов, заставляя их текстуры двигаться в противоположных направлениях. Это создает интересный визуальный паттерн.

update ()
{
    let x = 1;
    for (let i = 0; i < this.images.length; ++i)
    {
        this.images[i].tilePositionX += x;
        x *= -1;
    }
    this.iter += 0.01;
}

Настройка игры: объект конфигурации

Запуск игры происходит после создания экземпляра Phaser.Game, которому передается объект конфигурации. В нем задаются базовые параметры: тип рендерера (WEBGL для лучшей производительности), размеры холста, цвет фона, идентификатор HTML-элемента для встраивания и класс сцены, которая будет запущена первой.

const config = {
    type: Phaser.WEBGL,
    width: 800,
    height: 600,
    backgroundColor: '#2d2d2d',
    parent: 'phaser-example',
    scene: Example
};

const game = new Phaser.Game(config);

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

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