О чем этот пример
Tile Sprite — мощный инструмент для создания бесконечно прокручивающихся фонов и текстурных поверхностей. Но что, если нужно менять саму текстуру спрайта во время выполнения игры? Этот пример демонстрирует, как динамически изменять отдельный кадр (frame) у Tile Sprite, сохраняя при этом его основное свойство — плавную тайловую прокрутку. Такой подход полезен для создания анимированных фонов, меняющихся локаций или эффектов постепенной трансформации окружения.
Версия 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.atlas('atlas', 'assets/atlas/megaset-2.png', 'assets/atlas/megaset-2.json');
}
create ()
{
const atlasTexture = this.textures.get('atlas');
const frames = atlasTexture.getFrameNames();
frames.splice(frames.indexOf('platform'), 1);
this.ts = this.add.tileSprite(0, 0, 800, 600, '__MISSING').setOrigin(0);
this.add.text(10, 10, 'Click to change frame', { font: '16px Courier', fill: '#ffffff' });
this.input.on('pointerdown', () =>
{
this.ts.setTexture('atlas', Phaser.Utils.Array.GetRandom(frames));
});
}
update ()
{
const x = 1;
this.ts.tilePositionX += x;
this.ts.tilePositionY += x / 2;
this.iter += 0.01;
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Загрузка атласа и подготовка кадров
В методе preload загружается текстура-атлас, содержащий множество кадров (спрайтов). Ключевой момент происходит в create. Сначала мы получаем ссылку на загруженную текстуру.
const atlasTexture = this.textures.get('atlas');
const frames = atlasTexture.getFrameNames();
Метод getFrameNames() возвращает массив со всеми именами кадров внутри атласа. Далее из этого массива удаляется один конкретный кадр ('platform'), чтобы он не участвовал в случайном выборе. Это демонстрирует, как можно фильтровать контент для последующего использования.
Создание Tile Sprite с заглушкой
Сам Tile Sprite создаётся с использованием специального ключа текстуры '__MISSING'. Это встроенная в Phaser текстура-заглушка (розово-чёрная клетка), которая используется, когда запрошенная текстура не найдена.
this.ts = this.add.tileSprite(0, 0, 800, 600, '__MISSING').setOrigin(0);
Установка .setOrigin(0) привязывает точку начала координат спрайта (0,0) к его левому верхнему углу, что удобно для фонов, занимающих весь экран. На этом этапе спрайт отображает заглушку, так как его настоящая текстура ещё не назначена.
Динамическая смена кадра по клику
Интерактивность добавляется через обработчик события клика мыши (pointerdown). При каждом клике вызывается метод setTexture для нашего Tile Sprite.
this.input.on('pointerdown', () => {
this.ts.setTexture('atlas', Phaser.Utils.Array.GetRandom(frames));
});
Метод setTexture принимает два аргумента: ключ текстуры (в нашем случае 'atlas') и имя конкретного кадра внутри этой текстуры. Имя кадра выбирается случайным образом из подготовленного ранее массива frames с помощью утилиты Phaser.Utils.Array.GetRandom. Это мгновенно меняет визуальное содержимое Tile Sprite.
Прокрутка фона в update
Магия Tile Sprite проявляется в методе update, который выполняется каждый кадр. Здесь изменяются свойства tilePositionX и tilePositionY.
this.ts.tilePositionX += x;
this.ts.tilePositionY += x / 2;
Эти свойства управляют смещением тайловой текстуры внутри спрайта. Их инкрементальное увеличение создаёт эффект плавного, бесконечно прокручивающегося фона. Важно: даже после смены кадра через setTexture, прокрутка продолжает работать для нового изображения, так как меняется именно базовый кадр, а не отдельный экземпляр спрайта.
Что попробовать дальше
Сочетание Tile Sprite.setTexture() и изменения tilePosition открывает много возможностей. Вы можете создавать циклы дня и ночи, плавно меняя фон от утреннего к ночному кадру, или реализовать фоновую анимацию, где разные кадры сменяют друг друга по таймеру, а не по клику. Попробуйте заменить клик на автоматическую смену кадра каждые N секунд или привязать выбор кадра к прогрессу игрока.
