О чем этот пример
Создание игрового фона с плавной анимацией — классическая задача, которую можно решить разными способами. Phaser предлагает для этого удобный инструмент — объект `TileSprite`. В этой статье мы разберем пример, где два таких объекта с разными текстурами и размерами создают эффект динамического фона с параллаксом. Вы узнаете, как создать TileSprite, управлять положением его текстуры в реальном времени и комбинировать его с другими игровыми объектами для создания визуальной глубины.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
iter = 0;
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');
this.load.image('bunny', 'assets/sprites/bunny.png');
this.load.bitmapFont('desyrel', 'assets/fonts/bitmap/desyrel.png', 'assets/fonts/bitmap/desyrel.xml');
}
create ()
{
this.image0 = this.add.tileSprite(400, 300, 500, 500, 'image0');
this.add.sprite(400, 300, 'bunny');
this.image1 = this.add.tileSprite(400, 300, 150, 150, 'image1');
this.add.bitmapText(0, 0, 'desyrel', 'Hello World');
}
update ()
{
this.image0.tilePositionX = Math.cos(this.iter) * 400;
this.image0.tilePositionY = Math.sin(this.iter) * 400;
this.image1.tilePositionX = Math.cos(-this.iter) * 400;
this.image1.tilePositionY = Math.sin(-this.iter) * 400;
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);
Что такое TileSprite и зачем он нужен
TileSprite — это особый тип спрайта в Phaser, текстура которого может быть "замощена" (заполнена тайлами) по всей площади объекта. Это особенно полезно для создания больших фонов, узоров или анимированных текстур, которые должны плавно перемещаться, создавая эффект бесконечного скроллинга или динамического фона.
В отличие от обычного спрайта, который просто отображает текстуру в своих границах, TileSprite позволяет управлять смещением (tilePosition) и масштабом (tileScale) внутренней текстуры независимо от размера и положения самого объекта на сцене.
this.image0 = this.add.tileSprite(400, 300, 500, 500, 'image0');
Инициализация и настройка сцены
В методе preload() загружаются все необходимые ресурсы: две картинки для тайлов (image0, image1), отдельный спрайт (bunny) и bitmap-шрифт. Обратите внимание, что setBaseURL задает базовый путь для всех последующих загрузок, что упрощает указание относительных путей.
В методе create() происходит создание всех игровых объектов. Сначала создается большой TileSprite image0, который будет служить основным фоном. Затем поверх него добавляется обычный спрайт bunny, чтобы показать, как объекты могут накладываться друг на друга. После этого создается второй, меньший по размеру, TileSprite image1. Он будет двигаться в противофазе первому, создавая эффект параллакса. Наконец, добавляется статичный текст.
create ()
{
this.image0 = this.add.tileSprite(400, 300, 500, 500, 'image0');
this.add.sprite(400, 300, 'bunny');
this.image1 = this.add.tileSprite(400, 300, 150, 150, 'image1');
this.add.bitmapText(0, 0, 'desyrel', 'Hello World');
}
Динамическая анимация тайлов
Вся "магия" происходит в методе update(), который вызывается на каждом кадре игры. Здесь изменяются свойства tilePositionX и tilePositionY для обоих объектов TileSprite.
Переменная this.iter увеличивается на 0.01 каждый кадр, обеспечивая плавное изменение угла. Значения tilePosition вычисляются с помощью тригонометрических функций Math.cos и Math.sin, которые, будучи умноженными на 400, задают амплитуду движения текстуры по кругу.
Ключевой момент: для image1 используется отрицательный угол (-this.iter). Это заставляет его текстуру двигаться по кругу в противоположном направлении относительно image0, создавая сложный и визуально интересный параллакс-эффект.
update ()
{
this.image0.tilePositionX = Math.cos(this.iter) * 400;
this.image0.tilePositionY = Math.sin(this.iter) * 400;
this.image1.tilePositionX = Math.cos(-this.iter) * 400;
this.image1.tilePositionY = Math.sin(-this.iter) * 400;
this.iter += 0.01;
}
Структура конфигурации игры
Конфигурация игры задает основные параметры, такие как тип рендерера (CANVAS), размеры окна, цвет фона и корневую сцену. В данном примере используется рендерер на основе Canvas (Phaser.CANVAS).
Свойство parent указывает ID HTML-элемента, в который будет встроен canvas игры. Это позволяет легко интегрировать игру в существующую веб-страницу. После создания конфигурационного объекта инстанциируется класс Phaser.Game, который запускает игровой цикл.
const config = {
type: Phaser.CANVAS,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что попробовать дальше
TileSprite в Phaser — мощный инструмент для создания динамических фонов и текстурных эффектов. Изменяя tilePosition и tileScale в реальном времени, можно имитировать движение камеры, поток воды, огонь или космическую пыль. Для экспериментов попробуйте: заменить тригонометрические функции на линейное изменение для эффекта бесконечного скролла, анимировать свойство tileScale для "пульсирующего" фона, или использовать маску на одном из TileSprite, чтобы создать эффект просвета в движущемся узоре.
