О чем этот пример
Phaser 3 в связке с плагином Spine позволяет создавать сложные анимации персонажей, управлять ими как единой группой и добавлять динамические эффекты. Эта статья разбирает пример, где Spine-персонаж масштабируется вместе с контейнером, а камера создает эффект пульсации. Вы научитесь правильно загружать Spine-ассеты, управлять их отображением и комбинировать с системой камер Phaser для оживления игровой сцены.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
let spineboy
let container
class Example extends Phaser.Scene
{
constructor ()
{
super({
pack: {
files: [
{ type: 'scenePlugin', key: 'SpinePlugin', url: 'plugins/3.8.95/SpinePluginDebug.js', sceneKey: 'spine' }
]
}
});
}
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('logo', 'assets/sprites/phaser.png');
this.load.setPath('assets/spine/3.8/demos/');
this.load.spine('set1', 'demos.json', [ 'atlas1.atlas' ], true);
}
create ()
{
this.add.image(0, 0, 'logo').setOrigin(0);
container = this.add.spineContainer()
spineboy = this.add.spine(400, 600, 'set1.spineboy', 'idle', true);
container.add(spineboy)
container.setScale(0.5)
}
update(time, delta)
{
this.cameras.main.setZoom(Math.sin(time / 1000));
}
}
const config = {
type: Phaser.CANVAS,
parent: 'phaser-example',
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
scene: Example
};
const game = new Phaser.Game(config);
Подготовка и загрузка ассетов
В Phaser 3 работа со Spine-анимациями требует предварительной настройки плагина и корректной загрузки файлов. В конструкторе сцены указывается загрузка SpinePlugin, который обеспечивает поддержку формата Spine.
constructor ()
{
super({
pack: {
files: [
{ type: 'scenePlugin', key: 'SpinePlugin', url: 'plugins/3.8.95/SpinePluginDebug.js', sceneKey: 'spine' }
]
}
});
}
В методе preload задаются базовые пути и загружаются необходимые ресурсы: спрайт для фона и Spine-ассет. Обратите внимание, что для Spine указывается ключ set1, JSON-файл с данными анимации (demos.json), атлас текстур (atlas1.atlas) и флаг true для загрузки в формате JSON.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('logo', 'assets/sprites/phaser.png');
this.load.setPath('assets/spine/3.8/demos/');
this.load.spine('set1', 'demos.json', [ 'atlas1.atlas' ], true);
}
Создание контейнера и Spine-объекта
В методе create размещаются объекты на сцене. Сначала добавляется фоновое изображение с логотипом Phaser, затем создается специальный контейнер для Spine-объектов с помощью this.add.spineContainer(). Этот контейнер позволяет группировать несколько Spine-персонажей и применять к ним общие трансформации.
create ()
{
this.add.image(0, 0, 'logo').setOrigin(0);
container = this.add.spineContainer()
spineboy = this.add.spine(400, 600, 'set1.spineboy', 'idle', true);
container.add(spineboy)
container.setScale(0.5)
}
Spine-персонаж создается через this.add.spine(), где задаются координаты (400, 600), ключ ассета (set1.spineboy), начальная анимация (idle) и флаг автоматического воспроизведения (true). После создания объект добавляется в контейнер, и ко всему контейнеру применяется масштабирование в 0.5 раза. Это уменьшает и персонажа, и любые другие объекты внутри контейнера.
Динамическое управление камерой
Метод update вызывается на каждом кадре игры и здесь используется для создания пульсирующего эффекта зумирования камеры. Значение зума вычисляется на основе синуса от текущего игрового времени, что дает плавное циклическое изменение.
update(time, delta)
{
this.cameras.main.setZoom(Math.sin(time / 1000));
}
this.cameras.main ссылается на основную камеру сцены. Метод setZoom() изменяет масштаб отображения всей сцены. Использование Math.sin(time / 1000) гарантирует, что зум будет колебаться между -1 и 1 с периодом около 6.28 секунд (2 * π * 1000 мс). Визуально это создает эффект "дыхания" или пульсации всей сцены, включая Spine-персонажа и фон.
Конфигурация игры и инициализация
Ключевой момент — конфигурация рендерера. В примере явно указан Phaser.CANVAS, что важно для корректной работы Spine в некоторых окружениях, особенно при отладке или специфичных настройках производительности.
const config = {
type: Phaser.CANVAS,
parent: 'phaser-example',
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
scene: Example
};
После определения конфигурации создается экземпляр игры. Это запускает весь жизненный цикл Phaser: инициализацию, загрузку ресурсов, создание сцены и начало игрового цикла с вызовами update.
const game = new Phaser.Game(config);
Что попробовать дальше
Этот пример демонстрирует базовое использование Spine-анимаций в Phaser 3 с группировкой через контейнеры и динамическим управлением камерой. Для экспериментов попробуйте: добавить в контейнер несколько Spine-объектов с разными анимациями, изменить формулу зумирования камеры на более сложную (например, с использованием Math.cos или комбинации функций), или применить другие трансформации к контейнеру (вращение, смещение). Также можно поэкспериментировать с переключением анимаций персонажа по клику или таймеру, используя методы объекта spineboy.
