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

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

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    iter = 0;
    ts;

    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.image('mushroom', 'assets/sprites/mushroom2.png');
    }

    create ()
    {
        //  Our container
        const container = this.add.container(400, 300).setName('conty');

        this.ts = this.add.tileSprite(0, 0, 400, 600, 'mushroom').setName('tiley');
        container.add(this.ts);

        const image = this.add.image(0, 0, 'mushroom').setName('mushy').setScale(4);
        container.add(image);

        this.input.on('pointerup', function ()
        {

            this.scene.stop();
        
        }, this);
    }

    update ()
    {
        this.ts.tilePositionX = Math.cos(-this.iter) * 400;
        this.ts.tilePositionY = Math.sin(-this.iter) * 400;

        this.iter += 0.01;
    }
}

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

const game = new Phaser.Game(config);

Что такое Container и TileSprite?

Контейнер (Container) — это специальный игровой объект, который может содержать в себе другие объекты (спрайты, текст, другие контейнеры) и управлять ими как единым целым. Все дочерние объекты наследуют преобразования (позицию, вращение, масштаб) родительского контейнера.

Плиточный спрайт (TileSprite) — это спрайт, текстура которого может повторяться (плитковаться). Его основное преимущество — возможность сдвигать текстуру с помощью свойств tilePositionX и tilePositionY, создавая эффект бесконечного скроллинга или анимации.

В нашем примере мы поместим TileSprite и обычный Image в один контейнер, чтобы продемонстрировать их совместную работу.

Создание контейнера и добавление объектов

В методе create() сцены мы создаем контейнер и два спрайта. Важно отметить, что координаты дочерних объектов задаются относительно позиции контейнера.

// Создаем контейнер в центре экрана
const container = this.add.container(400, 300).setName('conty');

// Создаем TileSprite с центром в точке (0,0) контейнера
this.ts = this.add.tileSprite(0, 0, 400, 600, 'mushroom').setName('tiley');
// Добавляем TileSprite в контейнер
container.add(this.ts);

// Создаем обычное изображение и также добавляем его в контейнер
const image = this.add.image(0, 0, 'mushroom').setName('mushy').setScale(4);
container.add(image);

Оба спрайта (this.ts и image) создаются с координатами (0,0), но это локальные координаты внутри контейнера. Их глобальная позиция на экране будет определяться позицией контейнера (400, 300). Метод setName() полезен для отладки, чтобы идентифицировать объекты в инструментах разработчика.

Анимация плиточной текстуры

Магия TileSprite раскрывается в методе update(), который вызывается на каждом кадре игры. Мы изменяем свойства tilePositionX и tilePositionY, чтобы сдвигать текстуру спрайта.

update ()
{
    // Сдвигаем текстуру по X и Y по круговой траектории
    this.ts.tilePositionX = Math.cos(-this.iter) * 400;
    this.ts.tilePositionY = Math.sin(-this.iter) * 400;

    // Увеличиваем угол для следующего кадра
    this.iter += 0.01;
}

Здесь this.iter — это переменная-счетчик, которая плавно увеличивается. Используя тригонометрические функции Math.cos и Math.sin, мы рассчитываем координаты сдвига текстуры, создавая плавное круговое движение. Множитель 400 определяет амплитуду (радиус) этого движения. Обычный спрайт image внутри контейнера остается статичным, демонстрируя, что анимируется именно текстура TileSprite, а не его положение.

Настройка сцены и игры

Код инициализации игры стандартен. Мы передаем наш класс сцены Example в конфигурацию.

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    backgroundColor: '#010101',
    parent: 'phaser-example',
    scene: Example // Указываем нашу сцену
};

const game = new Phaser.Game(config);

Обратите внимание на обработчик события pointerup, который останавливает сцену по клику. Это стандартный прием для примеров.

this.input.on('pointerup', function ()
{
    this.scene.stop();
}, this);

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

Сочетание Container и TileSprite открывает мощные возможности для создания сложной графики. TileSprite, анимированный через tilePosition, позволяет легко реализовать бегущий фон, текущую воду, мерцающие звезды или другие повторяющиеся текстуры, которые являются частью更大的 составного объекта. Для экспериментов попробуйте

  1. Анимировать несколько TileSprite внутри одного контейнера с разной скоростью для эффекта параллакса
  2. Вращать или масштабировать весь контейнер и наблюдать, как анимация текстуры следует за этими преобразованиями
  3. Использовать tileScaleX/Y для динамического изменения масштаба самой плиточной текстуры