О чем этот пример

Импорт анимаций из Aseprite в Phaser значительно ускоряет разработку игр. Вместо ручного описания кадров и временных интервалов вы загружаете готовый спрайт-лист и JSON-файл с метаданными, созданные в редакторе. Это позволяет дизайнерам и аниматорам работать в удобном инструменте, а разработчикам — легко интегрировать результат в игру, управляя анимациями через код. Данный пример показывает, как загрузить анимации персонажа "паладина" и создать интерактивный интерфейс для их переключения.

Версия 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/animations/aseprite/';

        this.load.aseprite('paladin', 'paladin.png', 'paladin.json');
    }

    create ()
    {
        const tags = this.anims.createFromAseprite('paladin');

        const sprite = this.add.sprite(500, 300).play({ key: 'Magnum Break', repeat: -1 }).setScale(6);

        for (let i = 0; i < tags.length; i++)
        {
            const label = this.add.text(32, 32 + (i * 16), tags[i].key, { color: '#00ff00' });

            label.setInteractive();
        }

        this.input.on('gameobjectdown', (pointer, obj) =>
        {

            sprite.play({
                key: obj.text,
                repeat: -1
            });

        });

        this.input.on('gameobjectover', (pointer, obj) =>
        {

            obj.setColor('#ff00ff');

        });

        this.input.on('gameobjectout', (pointer, obj) =>
        {

            obj.setColor('#00ff00');

        });
    }
}

const config = {
    type: Phaser.AUTO,
    parent: 'phaser-example',
    width: 800,
    height: 600,
    pixelArt: true,
    scene: Example
};

const game = new Phaser.Game(config);

Загрузка анимаций Aseprite

В методе preload() мы загружаем данные, необходимые для создания анимаций. Ключевой метод — this.load.aseprite(). Он принимает три аргумента: текстовый ключ для идентификации ассета, путь к изображению (спрайт-листу) и путь к JSON-файлу с данными об анимациях, который экспортируется из Aseprite.

this.load.aseprite('paladin', 'paladin.png', 'paladin.json');

Также в коде задаётся базовый URL и путь для загрузки ассетов, что удобно для организации файлов. Важно отметить, что для корректного отображения пиксель-арт графики в конфигурации игры установлен флаг pixelArt: true.

Создание анимаций и спрайта

В методе create() происходит основная работа. Сначала все анимации, описанные в JSON-файле Aseprite, создаются в системе анимаций Phaser с помощью метода this.anims.createFromAseprite(). Он автоматически генерирует объекты анимаций на основе тегов (tags), заданных в редакторе, и возвращает массив этих анимаций.

const tags = this.anims.createFromAseprite('paladin');

Затем создаётся спрайт, который будет проигрывать анимации. Ему сразу задаётся начальная анимация 'Magnum Break' с бесконечным повторением и увеличенный масштаб для наглядности.

const sprite = this.add.sprite(500, 300).play({ key: 'Magnum Break', repeat: -1 }).setScale(6);

Интерактивный интерфейс для переключения анимаций

Чтобы дать возможность переключать анимации, в примере создаётся список из текстовых меток. Для каждой анимации в массиве tags создаётся объект текста (Phaser.GameObjects.Text). Каждая метка делается интерактивной с помощью метода setInteractive().

for (let i = 0; i < tags.length; i++)
{
    const label = this.add.text(32, 32 + (i * 16), tags[i].key, { color: '#00ff00' });
    label.setInteractive();
}

Далее настраивается обработка событий ввода. Событие gameobjectdown (клик или касание) переключает анимацию у основного спрайта на ту, название которой соответствует тексту нажатой метки.

this.input.on('gameobjectdown', (pointer, obj) =>
{
    sprite.play({
        key: obj.text,
        repeat: -1
    });
});

События gameobjectover и gameobjectout меняют цвет метки при наведении и уходе курсора, обеспечивая визуальную обратную связь.

this.input.on('gameobjectover', (pointer, obj) =>
{
    obj.setColor('#ff00ff');
});

this.input.on('gameobjectout', (pointer, obj) =>
{
    obj.setColor('#00ff00');
});

Что попробовать дальше

Пример демонстрирует мощный и удобный пайплайн для работы с анимациями из Aseprite в Phaser. Вы можете легко загружать сложные наборы анимаций и управлять ими в рантайме. Для экспериментов попробуйте загрузить свой собственный спрайт-лист из Aseprite, изменить логику переключения анимаций (например, по таймеру или в зависимости от состояния игрока) или добавить управление скоростью проигрывания анимации через метод setTimeScale().