О чем этот пример
Импорт анимаций из Aseprite — мощный способ оживить вашего игрового персонажа, избегая ручного создания кадров в коде. В этом примере показана базовая загрузка двух спрайтшитов (головы и тела) и автоматическое создание анимационных таймлайнов на основе тегов, экспортированных из Aseprite. Это экономит часы работы и позволяет дизайнерам напрямую влиять на игровой процесс.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.path = 'assets/bugs/';
this.load.aseprite('Head', 'MainChrHead.png', 'MainChrHead.json');
this.load.aseprite('Body', 'MainChr.png', 'MainChr.json');
}
create ()
{
this.add.sprite(100, 100, 'Head', '0').setScale(4);
this.add.sprite(300, 100, 'Body', '0').setScale(4);
// console.log(this.cache.json.get('Head'));
// console.log(this.cache.json.get('Body'));
const BodyTags = this.anims.createFromAseprite("Body");
const HeadTags = this.anims.createFromAseprite("Head");
// console.log(BodyTags[0].frames[0], HeadTags[0].frames[0]);
// console.log(BodyTags, HeadTags);
// const tags = this.anims.createFromAseprite('paladin');
// console.log(tags);
// const step = this.anims.createFromAseprite('paladin', 'step');
// const delay = this.anims.createFromAseprite('paladin', 'Delay');
// const release = this.anims.createFromAseprite('paladin', 'release');
// console.log(step);
// console.log(delay);
// console.log(release);
// const sprite = this.add.sprite(500, 300).play({ key: 'step', repeat: -1 }).setScale(6);
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
backgroundColor: '#2d2d88',
scene: Example
};
const game = new Phaser.Game(config);
Загрузка Aseprite-ассетов
Метод preload() сцены отвечает за загрузку всех необходимых ресурсов. Для работы с Aseprite файлами используется специальный загрузчик load.aseprite().
this.load.aseprite('Head', 'MainChrHead.png', 'MainChrHead.json');
this.load.aseprite('Body', 'MainChr.png', 'MainChr.json');
Первый аргумент — это ключ (key), под которым ассет будет доступен в кеше. Второй и третий аргументы — это пути к PNG-изображению и JSON-файлу с метаданными (размерами кадров и тегами анимаций), которые экспортирует Aseprite. Важно предварительно настроить базовый URL и путь, чтобы не указывать полные адреса для каждого файла.
Создание статичных спрайтов
В методе create() сначала создаются два простых спрайта для визуальной проверки загруженных текстур.
this.add.sprite(100, 100, 'Head', '0').setScale(4);
this.add.sprite(300, 100, 'Body', '0').setScale(4);
Первый аргумент add.sprite() — координаты X и Y. Второй — ключ текстуры (например, 'Head'). Третий, необязательный аргумент — это индекс или имя кадра. Здесь '0' указывает на самый первый кадр из загруженного спрайтшита. Метод setScale(4) увеличивает спрайт в 4 раза для наглядности. На этом этапе спрайты статичны.
Магия createFromAseprite
Ключевой метод для работы с анимациями — this.anims.createFromAseprite(). Он парсит JSON-данные, загруженные из Aseprite, и автоматически создает в менеджере анимаций (this.anims) готовые анимации на основе тегов (tags).
const BodyTags = this.anims.createFromAseprite("Body");
const HeadTags = this.anims.createFromAseprite("Head");
Если вызвать метод только с ключом текстуры (как в примере), он создаст анимации для ВСЕХ тегов, найденных в JSON-файле этого ассета. Метод возвращает массив созданных анимаций. Каждая анимация получает ключ (key), совпадающий с именем тега из Aseprite. Эти анимации теперь можно использовать в любом спрайте, используя sprite.play('имя_тега').
Как это работает под капотом
Phaser загружает JSON-файл от Aseprite в кеш (this.cache.json). Этот файл содержит массив frames с координатами каждого кадра на спрайтшите и массив meta.frameTags с именами анимаций (тегами) и диапазонами кадров.
// Для отладки можно посмотреть структуру данных:
// console.log(this.cache.json.get('Head'));
Метод createFromAseprite проходит по массиву frameTags и для каждого тега регистрирует новую анимацию, используя кадры из указанного диапазона. Все параметры анимации (задержки между кадрами) берутся из данных Aseprite. Это избавляет разработчика от ручного описания каждого кадра анимации в коде игры.
Расширенное использование: создание конкретных анимаций
Метод createFromAseprite может создавать не все анимации разом, а только конкретные, указанные по имени тега. Это полезно для оптимизации или выборочной загрузки.
// Пример из закомментированного кода:
// const step = this.anims.createFromAseprite('paladin', 'step');
Вторым аргументом можно передать строку с именем одного тега или массив строк с именами нескольких тегов. Метод вернет массив созданных анимаций (в случае одного тега — массив из одного элемента). Это дает точный контроль над тем, какие анимации будут зарегистрированы в системе.
Что попробовать дальше
Использование createFromAseprite кардинально упрощает pipeline «художник → игра». Все настройки анимации остаются в редакторе. Для экспериментов попробуйте
- Запустить анимацию на одном из созданных спрайтов, используя
sprite.play('имя_тега') - Экспортировать из Aseprite анимацию с разной длительностью кадров и убедиться, что Phaser корректно их учитывает
- Загрузить спрайтшит, содержащий несколько персонажей (атки, айдлы) в разных тегах, и переключать их в зависимости от действий игрока
