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

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

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    iter = 0;
    tween;
    image1;
    image0;

    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.image('image0', 'assets/pics/ra-einstein.png');
        this.load.image('image1', 'assets/sprites/mushroom2.png');
    }

    create ()
    {
        this.image0 = this.add.tileSprite(400, 300, 800, 600, 'image0');
        this.image1 = this.add.tileSprite(400, 300, 250, 250, 'image1');

        this.tween = this.tweens.addCounter({
            from: 1,
            to: 2,
            duration: 5000,
            ease: 'Sine.easeInOut',
            yoyo: true,
            repeat: -1
        });
    }

    update ()
    {
        this.image0.tilePositionX = Math.cos(this.iter) * 700;
        this.image0.tilePositionY = Math.sin(this.iter) * 500;

        this.image0.tileScaleX = this.tween.getValue();
        this.image0.tileScaleY = this.tween.getValue();

        this.image1.tilePositionX = Math.cos(-this.iter) * 400;
        this.image1.tilePositionY = Math.sin(-this.iter) * 400;

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

Что такое TileSprite и зачем он нужен

TileSprite — это особый игровой объект в Phaser, который отображает текстуру с возможностью тайлинга (повторения). В отличие от обычного Sprite, его изображение не обрезается под размер объекта, а бесшовно заполняет отведённую область, как плитка. Это ключевое свойство позволяет сдвигать (tilePosition) и масштабировать (tileScale) саму текстуру внутри контейнера, создавая иллюзию движения или деформации.

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

Создание и настройка TileSprite

Объекты создаются в методе create сцены. Метод this.add.tileSprite принимает координаты (x, y), ширину, высоту и ключ загруженного изображения.

this.image0 = this.add.tileSprite(400, 300, 800, 600, 'image0');
this.image1 = this.add.tileSprite(400, 300, 250, 250, 'image1');

Первый спрайт (image0) растягивается на весь экран (800x600), второй (image1) — это меньший квадрат по центру. Оба используют разные текстуры. Важно: исходные изображения должны быть либо бесшовными, либо такими, где шов не будет заметен при повторении.

Анимация смещения текстуры (tilePosition)

Динамика достигается за счёт изменения свойств tilePositionX и tilePositionY в методе update. Эти свойства сдвигают текстуру по соответствующим осям. В примере для расчёта смещения используются тригонометрические функции Math.cos и Math.sin, что создаёт плавное круговое движение.

this.image0.tilePositionX = Math.cos(this.iter) * 700;
this.image0.tilePositionY = Math.sin(this.iter) * 500;

this.image1.tilePositionX = Math.cos(-this.iter) * 400;
this.image1.tilePositionY = Math.sin(-this.iter) * 400;

this.iter += 0.01;

Переменная iter увеличивается каждый кадр, меняя аргумент для функций. Умножение на разные числа (700, 500, 400) задаёт амплитуду (радиус) движения. Знак -this.iter для image1 заставляет текстуру двигаться в противоположную сторону, создавая интересный визуальный контраст.

Плавное масштабирование текстуры (tileScale) с помощью Tween

Свойства tileScaleX и tileScaleY управляют масштабом тайлированной текстуры. Значение 1 — исходный размер, 2 — увеличение в два раза. Для плавной анимации масштаба используется система Tween. В create создаётся счётчик (tweens.addCounter), который циклически меняет значение от 1 до 2 и обратно.

this.tween = this.tweens.addCounter({
    from: 1,
    to: 2,
    duration: 5000,
    ease: 'Sine.easeInOut',
    yoyo: true,
    repeat: -1
});

Затем в update текущее значение этого твина присваивается свойствам масштаба.

this.image0.tileScaleX = this.tween.getValue();
this.image0.tileScaleY = this.tween.getValue();

Это заставляет текстуру image0 равномерно "дышать", плавно увеличиваясь и уменьшаясь. Параметры yoyo: true и repeat: -1 обеспечивают бесконечное повторение цикла.

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

TileSprite — это ваш инструмент для оживления игрового мира без чрезмерных затрат ресурсов. Комбинируя анимацию позиции и масштаба, можно создавать сложные эффекты. Для экспериментов попробуйте: привязать tilePosition к скорости игрока для параллакса, использовать разные easing-функции для твинов, анимировать tileScaleX и tileScaleY независимо для эффекта сжатия или наложить на TileSprite маску для создания анимированных порталов.