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

Создание анимаций из атласов спрайтов — рутинная задача. Вручную прописывать десятки кадров с нумерацией — долго и чревато ошибками. К счастью, Phaser предоставляет мощный метод `generateFrameNames`, который автоматически генерирует массив кадров по заданному шаблону. Эта статья покажет, как эффективно использовать этот метод для быстрого создания сложных анимаций, экономя время и упрощая поддержку кода.

Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.

Живой запуск

Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.

Исходный код


class Example extends Phaser.Scene
{
    constructor ()
    {
        super();
    }

    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.atlas('gems', 'assets/tests/columns/gems.png', 'assets/tests/columns/gems.json');
    }

    create ()
    {
        this.add.text(400, 32, 'Check the source code for comments', { color: '#00ff00' }).setOrigin(0.5, 0);

        //  The gems.json file has the following frames in it:

        //  diamond_0000 to diamond_0015

        //  So we use:

        //  generateFrameNames('gems', { prefix: 'diamond_', end: 15, zeroPad: 4 })

        //  Because the prefix is 'diamond_', it has 4 zeros in it (0000), which start at 0000 and end at 0015.

        //  If the frame names had a suffix, i.e. 'diamond_0000.png' then you could do:

        //  generateFrameNames('gems', { prefix: 'diamond_', suffix: '.png', end: 15, zeroPad: 4 })

        this.anims.create({ key: 'diamond', frames: this.anims.generateFrameNames('gems', { prefix: 'diamond_', end: 15, zeroPad: 4 }), repeat: -1 });
        this.anims.create({ key: 'prism', frames: this.anims.generateFrameNames('gems', { prefix: 'prism_', end: 6, zeroPad: 4 }), repeat: -1 });
        this.anims.create({ key: 'ruby', frames: this.anims.generateFrameNames('gems', { prefix: 'ruby_', end: 6, zeroPad: 4 }), repeat: -1 });
        this.anims.create({ key: 'square', frames: this.anims.generateFrameNames('gems', { prefix: 'square_', end: 14, zeroPad: 4 }), repeat: -1 });

        this.add.sprite(400, 200, 'gems').play('diamond');
        this.add.sprite(400, 300, 'gems').play('prism');
        this.add.sprite(400, 400, 'gems').play('ruby');
        this.add.sprite(400, 500, 'gems').play('square');
    }
}

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

const game = new Phaser.Game(config);

Загрузка атласа и подготовка

Всё начинается с загрузки атласа спрайтов — изображения, содержащего все кадры анимации, и JSON-файла с их координатами. В нашем примере мы загружаем атлас с ключом 'gems'.

preload ()
{
    this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
    this.load.atlas('gems', 'assets/tests/columns/gems.png', 'assets/tests/columns/gems.json');
}

После загрузки в create() мы можем создавать анимации. Ключевой момент: кадры в JSON-файле имеют последовательные имена, такие как diamond_0000, diamond_0001 и так далее. Именно эту закономерность мы и будем использовать.

Метод generateFrameNames и его параметры

Метод this.anims.generateFrameNames() генерирует массив объектов-кадров для анимации на основе переданного шаблона. Он принимает два аргумента: ключ текстуры (атласа) и объект конфигурации.

Основные параметры конфигурации: - prefix: Префикс имени кадра (например, 'diamond_'). - end: Номер последнего кадра в последовательности. - zeroPad: Количество цифр в номере кадра. Если номер меньше, он будет дополнен нулями слева. - suffix: Суффикс имени кадра (например, '.png'), если он присутствует в исходных данных.

Вот как создаётся анимация для алмаза:

this.anims.create({
    key: 'diamond',
    frames: this.anims.generateFrameNames('gems', {
        prefix: 'diamond_',
        end: 15,
        zeroPad: 4
    }),
    repeat: -1
});

Этот код сгенерирует массив кадров для имён от diamond_0000 до diamond_0015. Параметр repeat: -1 задаёт бесконечное повторение анимации.

Создание нескольких анимаций из одного атласа

Один атлас часто содержит кадры для нескольких анимаций. Используя разные префиксы в вызове generateFrameNames, мы можем легко создать их все. В примере создаются четыре разные анимации: 'diamond', 'prism', 'ruby' и 'square'.

this.anims.create({ key: 'prism', frames: this.anims.generateFrameNames('gems', { prefix: 'prism_', end: 6, zeroPad: 4 }), repeat: -1 });
this.anims.create({ key: 'ruby', frames: this.anims.generateFrameNames('gems', { prefix: 'ruby_', end: 6, zeroPad: 4 }), repeat: -1 });
this.anims.create({ key: 'square', frames: this.anims.generateFrameNames('gems', { prefix: 'square_', end: 14, zeroPad: 4 }), repeat: -1 });

Обратите внимание, что анимации 'prism' и 'ruby' используют 7 кадров (от 0 до 6), а 'square' — 15 кадров (от 0 до 14). Метод гибко адаптируется под разные последовательности.

Воспроизведение анимаций на спрайтах

После регистрации анимаций в менеджере анимаций (this.anims), их можно проигрывать на любых спрайтах, использующих тот же текстурый атлас. Создаём спрайт и вызываем метод .play() с ключом нужной анимации.

this.add.sprite(400, 200, 'gems').play('diamond');
this.add.sprite(400, 300, 'gems').play('prism');
this.add.sprite(400, 400, 'gems').play('ruby');
this.add.sprite(400, 500, 'gems').play('square');

Каждый спрайт ссылается на текстуру 'gems', но проигрывает свою собственную последовательность кадров, определённую при создании анимации. Это классический и эффективный подход для работы с атласами.

Полная конфигурация игры

Для полноты картины приведём стандартную конфигурацию игры Phaser 3, которая запускает наш пример. Важный параметр pixelArt: true помогает сохранить чёткость пиксельной графики.

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

const game = new Phaser.Game(config);

Этот код инициализирует игровой экземпляр с настройками по умолчанию и запускает сцену Example, содержащую всю логику с анимациями.

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

Метод generateFrameNames — незаменимый инструмент для работы с последовательно пронумерованными кадрами в атласах. Он устраняет рутину и потенциальные ошибки при создании анимаций. Для экспериментов попробуйте: изменить параметр zeroPad на 2 для кадров вида diamond_00; добавить параметр start для начала последовательности не с нуля; использовать suffix, если имена кадров в JSON включают расширение файла. Это откроет полный контроль над процессом генерации.