О чем этот пример
При разработке игр с использованием Spine для анимаций часто возникает необходимость загрузить несколько скелетных моделей, использующих один и тот же атлас текстур. Это может быть полезно для оптимизации памяти и ускорения загрузки, когда разные персонажи или объекты разделяют части текстур. Однако, если сделать это неправильно, можно столкнуться с ошибками загрузки или некорректным отображением. В этой статье мы разберем пример из официального репозитория Phaser, который демонстрирует корректный подход к загрузке двух Spine-объектов, использующих один файл атласа (.atlas), но с разными путями к изображениям.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
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.setPath('assets/spine/3.8/coin');
this.load.spine('coin1', 'coin-pro.json', 'coin-pro.atlas');
this.load.setPath('assets/spine/3.8/coin2');
this.load.spine('coin2', 'coin-pro.json', 'coin-pro.atlas');
}
create ()
{
this.add.spine(300, 300, 'coin1', 'animation', true);
this.add.spine(600, 300, 'coin2', 'animation', true);
}
}
const config = {
type: Phaser.WEBGL,
parent: 'phaser-example',
width: 800,
height: 600,
backgroundColor: '#000000',
scene: Example
};
const game = new Phaser.Game(config);
Подготовка сцены и загрузка плагина Spine
Первым шагом является настройка сцены для работы с Spine-анимациями. Для этого в конструкторе класса сцены мы указываем конфигурацию для загрузки плагина SpinePlugin. Это важно, так как Spine не является частью ядра Phaser и подключается как внешний плагин.
constructor ()
{
super({
pack: {
files: [
{ type: 'scenePlugin', key: 'SpinePlugin', url: 'plugins/3.8.95/SpinePluginDebug.js', sceneKey: 'spine' }
]
}
});
}
Ключевые параметры здесь: type: 'scenePlugin' указывает на тип загружаемого файла, key — это внутренний ключ плагина, url — путь к JavaScript-файлу плагина, а sceneKey: 'spine' задает ключ, под которым плагин будет доступен в сцене (например, как this.spine или через this.add.spine).
Загрузка ресурсов с разными базовыми путями
В методе preload происходит загрузка двух Spine-скелетов. Оба используют один и тот же JSON-файл с данными анимации (coin-pro.json) и один файл атласа (coin-pro.atlas). Однако, изображения для этих атласов находятся в разных директориях (assets/spine/3.8/coin и assets/spine/3.8/coin2). Для корректной загрузки необходимо временно менять базовый путь с помощью this.load.setPath.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.setPath('assets/spine/3.8/coin');
this.load.spine('coin1', 'coin-pro.json', 'coin-pro.atlas');
this.load.setPath('assets/spine/3.8/coin2');
this.load.spine('coin2', 'coin-pro.json', 'coin-pro.atlas');
}
Метод this.load.setPath устанавливает относительный путь для последующих загрузок. Это позволяет загрузить один и тот же файл .atlas, но при этом Loader будет искать текстуры, на которые ссылается атлас, в указанной директории. Ключи 'coin1' и 'coin2' — это уникальные идентификаторы загруженных скелетов, которые будут использоваться при создании объектов.
Создание и отображение Spine-объектов
После загрузки ресурсов в методе create мы можем создавать экземпляры Spine-объектов. Каждый объект создается с использованием своего уникального ключа, загруженного ранее. Это позволяет иметь две независимые анимации, которые визуально могут отличаться, если текстуры в папках coin и coin2 разные.
create ()
{
this.add.spine(300, 300, 'coin1', 'animation', true);
this.add.spine(600, 300, 'coin2', 'animation', true);
}
Метод this.add.spine принимает координаты X и Y, ключ скелета (например, 'coin1'), имя анимации для проигрывания ('animation') и булево значение, указывающее, следует ли проигрывать анимацию в цикле (true). Оба объекта будут отображены на сцене в разных позициях.
Конфигурация и запуск игры
Финальный шаг — настройка объекта конфигурации игры и ее инстанцирование. В конфиге мы указываем использование WebGL, что необходимо для корректной работы Spine, задаем размеры холста и передаем наш класс сцены.
const config = {
type: Phaser.WEBGL,
parent: 'phaser-example',
width: 800,
height: 600,
backgroundColor: '#000000',
scene: Example
};
const game = new Phaser.Game(config);
Параметр type: Phaser.WEBGL обеспечивает аппаратное ускорение рендеринга. parent — это ID HTML-элемента, в который будет встроен canvas. Черный фон (backgroundColor) помогает визуально выделить анимации. Создание экземпляра Phaser.Game с этой конфигурацией запускает весь жизненный цикл игры.
Что попробовать дальше
Этот пример наглядно показывает, как правильно загружать несколько Spine-скелетов, разделяющих один атлас, но имеющих разные наборы текстур. Ключевой момент — управление путями загрузки через setPath. Для экспериментов попробуйте изменить пути на свои ассеты, использовать разные имена анимаций или настроить параметры отображения, такие как масштаб или цвет tint. Также можно поэкспериментировать с загрузкой одного скелета, но с разными атласами, чтобы создать вариативность внешнего вида персонажей.
