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

TileSprite — это мощный объект Phaser для создания бесшовных текстур, которые можно «прокручивать», что идеально подходит для фонов, анимированных текстур или эффектов параллакса. В этой статье мы разберем, как создавать и анимировать несколько TileSprite, используя один текстурый атлас. Вы научитесь эффективно управлять их положением и создавать сложные визуальные эффекты с минимальным кодом, что особенно полезно для оптимизации игр с большим количеством движущихся элементов.

Версия 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.CANVAS,
    width: 800,
    height: 600,
    backgroundColor: '#2d2d2d',
    parent: 'phaser-example',
    scene: Example
};

const game = new Phaser.Game(config);

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

Перед созданием спрайтов необходимо загрузить текстуры. В Phaser для этого используется метод preload. В нашем примере загружается один текстурый атлас — это изображение, содержащее множество отдельных кадров (спрайтов) вместе с 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');
}

Метод setBaseURL задаёт базовый URL для всех последующих загрузок, что удобно, если ресурсы хранятся в одном месте. Затем load.atlas загружает сам атлас: первый аргумент — это ключ 'atlas', по которому мы будем обращаться к атласу в коде, второй — путь к PNG-изображению, третий — путь к JSON-файлу с разметкой.

Создание массива TileSprite

В методе create, который вызывается один раз после загрузки ресурсов, мы создаём пять объектов TileSprite. Каждый из них использует текстуру из загруженного атласа.

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;
}

Метод this.add.tileSprite принимает следующие аргументы: координаты X и Y, ширину, высоту, ключ атласа ('atlas') и имя конкретного кадра из этого атласа (например, 'atari400'). Мы размещаем спрайты по горизонтали с шагом в 160 пикселей (их ширину). Свойства originX и originY устанавливаются в 0 — это меняет точку привязки (origin) спрайта на его левый верхний угол. По умолчанию она находится в центре, но для удобства позиционирования в ряд мы сдвигаем её.

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

Основная «магия» происходит в методе update, который вызывается на каждом кадре игры. Здесь мы анимируем TileSprite, изменяя свойство tilePositionX.

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

Свойство tilePositionX определяет смещение внутренней текстуры (тайла) по оси X. Увеличивая его, мы создаём эффект плавного движения текстуры вправо, уменьшая — влево. В данном коде используется переменная `x, которая меняет знак на каждой итерации цикла (x *= -1). Это заставляет соседние TileSprite двигаться в противоположных направлениях, создавая интересный волнообразный эффект. Переменнаяiter` в примере увеличивается, но не используется — её можно применить для более сложной логики, например, зависящей от времени.

Конфигурация игры и запуск

Весь пример оборачивается в стандартную конфигурацию Phaser Game.

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

const game = new Phaser.Game(config);

Здесь задаются основные параметры: type — рендерер (Canvas), размеры окна, цвет фона, ID HTML-элемента (parent), в который будет встроена игра, и класс сцены. Создание экземпляра new Phaser.Game(config) запускает игровой цикл.

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

Использование TileSprite с атласами — это эффективный способ создания динамичных фонов и анимаций с минимальными затратами ресурсов. Вы можете экспериментировать: изменять tilePositionY для вертикального скролла, применять разные скорости для эффекта параллакса, масштабировать тайлы или комбинировать это со свойствами tileScale. Попробуйте загружать отдельные изображения вместо атласа или анимировать спрайты в зависимости от времени, используя переменную iter.