О чем этот пример
Загрузка ассетов — ключевой этап в разработке игр. Чаще всего для этого используют загрузочную сцену (preload), но Phaser 3 предлагает более гибкий подход: загрузку ресурсов прямо из конфигурации сцены. Это особенно полезно для небольших сцен, демо-примеров или когда нужно быстро прототипировать, не создавая отдельную сцену загрузки. В этой статье мы разберем, как задать спрайт-лист для анимации непосредственно в конструкторе класса сцены, используя свойство `pack`.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
constructor ()
{
super({
pack: {
files: [
{
type: 'spritesheet',
key: 'explosion',
url: 'assets/sprites/explosion.png',
frameConfig: { frameWidth: 64, frameHeight: 64, endFrame: 23 }
}
]
}
});
}
create ()
{
const config = {
key: 'explodeAnimation',
frames: this.anims.generateFrameNumbers('explosion', { start: 0, end: 23, first: 23 }),
frameRate: 20,
repeat: -1
};
this.anims.create(config);
this.add.sprite(400, 300, 'explosion').play('explodeAnimation');
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Концепция загрузки через `pack`
Phaser позволяет определить набор файлов для загрузки не только в методе preload() сцены, но и через статическое свойство pack в ее конфигурации. Этот набор загружается автоматически до создания (create) сцены, но после инициализации системы загрузки игры.
Такой подход идеален для изолированных примеров или сцен, которые должны быть самодостаточными. Все необходимые ресурсы объявляются прямо в классе, что делает код более понятным и сфокусированным.
Анализ кода: конструктор сцены
Вся магия происходит в конструкторе класса сцены. Мы вызываем super() и передаем объект конфигурации с единственным свойством pack. Внутри pack.files описывается массив файлов для загрузки.
constructor ()
{
super({
pack: {
files: [
{
type: 'spritesheet',
key: 'explosion',
url: 'assets/sprites/explosion.png',
frameConfig: { frameWidth: 64, frameHeight: 64, endFrame: 23 }
}
]
}
});
}
Разберем параметры объекта файла:
- type: 'spritesheet' указывает загрузчику, что это спрайт-лист.
- key: 'explosion' — уникальный ключ, по которому мы будем обращаться к этому ассету в коде.
- url: путь к файлу изображения.
- frameConfig: объект с параметрами для нарезки. frameWidth и frameHeight задают размер одного кадра. endFrame: 23 говорит системе, что всего в листе 24 кадра (с 0 по 23).
Создание и воспроизведение анимации
В методе create() мы работаем с уже загруженным спрайт-листом. Сначала создаем анимацию, используя кадры из этого листа.
const config = {
key: 'explodeAnimation',
frames: this.anims.generateFrameNumbers('explosion', { start: 0, end: 23, first: 23 }),
frameRate: 20,
repeat: -1
};
this.anims.create(config);
Функция this.anims.generateFrameNumbers генерирует массив объектов-кадров на основе ключа спрайт-листа ('explosion') и диапазона. Параметр first: 23 нестандартен для Phaser и в данном примере, похоже, не оказывает эффекта, так как анимация создается с кадрами от 0 до 23. Возможно, это опечатка в исходном примере. Обычно first используется, чтобы задать, какой кадр будет показан на спрайте до начала проигрывания анимации. Стандартный подход — указать start и end.
После создания анимации мы добавляем спрайт в сцену и запускаем на нем анимацию.
this.add.sprite(400, 300, 'explosion').play('explodeAnimation');
Здесь 'explosion' — это ключ текстуры (спрайт-листа), а 'explodeAnimation' — ключ созданной нами анимации. Метод .play() запускает ее воспроизведение.
Когда использовать этот подход?
Загрузка через pack в конструкторе — отличный выбор для:
1. **Небольших примеров и прототипов**, где хочется уместить всю логику в один файл.
2. **Самодостаточных модулей или мини-игр** внутри большого проекта, которые должны управлять своими ресурсами.
3. **Ситуаций, когда загрузка ресурсов жестко привязана к логике конкретной сцены**.
Однако для основного игрового проекта классический подход с отдельной сценой Preload или Boot предпочтительнее. Он централизует загрузку всех основных ассетов (звуков, изображений, данных), показывает прогресс-бар и обеспечивает лучший контроль над потоком загрузки.
Что попробовать дальше
Использование свойства pack в конфигурации сцены — это мощный и элегантный способ определить ресурсы, необходимые для ее работы, прямо в ее классе. Он делает код сцены более инкапсулированным и простым для понимания в изоляции.
**Идеи для экспериментов:**
1. Попробуйте загрузить через pack не только спрайт-лист, но и простое изображение (type: 'image') или атлас (type: 'atlas').
2. Создайте несколько сцен с разными наборами pack и переключайтесь между ними, наблюдая, как Phaser управляет загрузкой и выгрузкой ресурсов.
3. Проверьте, что произойдет, если указать в frameConfig неверный endFrame (больше, чем реальное количество кадров в изображении).
