Введение

Для разработки игр HTML5 у разработчиков есть несколько вариантов создания анимации. Мы используем Adobe Animate (ранее известный как Flash) и Flump для создания высококачественной анимации на основе ключевых кадров. Animate предоставляет нашим художникам стандартный инструмент анимации. Flump переводит анимации, созданные в Animate, и сериализованные данные временной шкалы в JSON или XML, а также растрирует векторную графику в атласы текстур.

К сожалению, Flump не очень широко распространен в сообществе разработчиков игр. Именно из-за этого он не имеет широкой поддержки в некоторых наиболее популярных игровых движках HTML5. Мы используем Phaser 2 для наших игр HTML5, который не поддерживает Flump. Чтобы решить эту проблему, мы написали плагин для Phaser, который будет загружать и воспроизводить анимации Flump.

Фламп против других вариантов

Итак, почему Фламп? По умолчанию Phaser 2 поддерживает два типа анимации: анимацию спрайтов флипбука и Spine. Анимация Flipbook — это стандартная анимация спрайтов, в которой вы меняете изображения местами, чтобы создать иллюзию движения. Spine — это инструмент скелетной анимации, который позволяет аниматорам анимировать отдельные части персонажа, прикрепляя их к костям.

Мы используем Flump вместо анимации флипбука из-за качества и потребления памяти. Flump обеспечивает плавную анимацию телевизионного качества, которая использует меньше памяти текстур.

Когда дело доходит до выбора Flump вместо Spine, речь идет о стоимости и рабочем процессе. Spine — отличный инструмент для анимации, популярный в разработке игр. Вы можете получить тот же уровень качества в Spine, что и в Adobe Animate; и он изначально поддерживается в Phaser. Так зачем использовать Flump вместо Spine? Просто, Spine стоит дорого. Его можно использовать в Phaser 2 бесплатно, однако инструменты анимации Spine имеют чрезвычайно высокие лицензионные сборы для среднего и крупного бизнеса. Стоимость лицензии увеличивается в зависимости от дохода компании. Хотя у Adobe Animate есть лицензионный сбор, он намного дешевле для частных лиц и компаний, которые уже используют Adobe Creative Cloud.

Мы также много работаем с медиа-брендами мирового уровня и часто адаптируем телевизионные анимации к игровому контенту. Возможность напрямую использовать телевизионную анимацию, созданную с помощью Adobe Animate, в наших играх обеспечивает более аутентичный опыт.

Технический сбой

Оригинальная среда выполнения

Плагин, который мы написали, основан на среде выполнения, написанной для инструмента экспорта Flump. Flump имеет открытый исходный код и распространяется под лицензией MIT. Это означало, что мы могли свободно использовать то, что нам нужно от Flump, чтобы заставить анимации работать в Phaser, однако это не был прямой порт. Поскольку Flump написан на ActionScript 3 для платформы Starling, перенос его на Phaser 2 означал интеграцию Flump, чтобы он плавно работал с движком.

Загрузка активов

Нашим первым шагом была реализация пользовательского загрузчика, который мы могли использовать с менеджером загрузки Phaser. Мы хотели иметь возможность использовать стандартный конвейер Phaser для загрузки ресурсов Flump. С нашим новым загрузчиком атласа Flump мы можем вызвать `game.load.flumpAtlas(…)`.

preload() {
    game.load.flumpAtlas(“demoLibrary”, “assets/library.json”, “assets/atlas0.png”);
}

Чтобы загрузить активы Flump, мы предоставляем ключ, который мы будем использовать для идентификации этих активов в объекте кеша. В данном случае наш ключ — «demoLibrary». Загрузчик сохранит данные `library.json`, используя ключ, и добавит ключ в качестве префикса к имени файла изображения. В нашем примере файл «assets/atlas0.png» хранится как «demoLibrary/atlas0.png». Нам нужно добавить префикс ключа библиотеки к нашим изображениям, потому что экспортер Flump не позволяет нам изменять схему именования, которую он использует при экспорте изображений атласа. Без библиотечного ключа с префиксом мы столкнулись бы с конфликтами имен, если бы были загружены активы для более чем одной библиотеки.

Создание библиотеки

После загрузки ресурсов Flump в кеш ресурсов Phaser мы инициализируем библиотеку Flump для использования ее ресурсов. Библиотека Flump — это коллекция текстур и символов фильмов, экспортированных из Animate. Каждый символ уникален для библиотеки, к которой он принадлежит, и мы хотели убедиться, что это останется в плагине.

create() {
    game.flump.add(“demoLibrary”);
}

Когда библиотека добавляется в плагин, он использует предоставленный нами ключ для извлечения всех необходимых ресурсов из кэша активов Phaser. Это включает в себя «library.json» и любые изображения атласа, к которым был добавлен префикс нашего пользовательского загрузчика. Как только данные будут получены, он проанализирует «library.json» и создаст данные кадра для каждого изображения атласа. С изображениями атласа, соединенными с данными кадра, атлас Flump можно использовать, как если бы это был любой другой атлас изображений.

game.image.add(0, 0, “demoLibrary/atlas0.png”, “orangeSquare”);

Портирование проигрывателя анимации

Интеграция наших ресурсов Flump в стандартный рабочий процесс Phaser позволила нам легко начать перенос проигрывателя анимации из экспортера Flump.

Мы начали с создания универсального объекта Symbol. Символ — это любой объект, который Flump использует для воспроизведения анимации. Сюда входят пустые объекты-заполнители, текстуры и видеоролики. На практике наш символ — это просто расширенное изображение фазера. Это позволяет нам назначать любые данные текстуры символов из атласа Flump. Это также позволяет объединять символы текстур, когда они не используются в фильме.

Когда Flump экспортирует анимацию с поворотами, он преобразует значения поворота в масштаб и наклон. Это означает, что плагину нужна поддержка перекоса изображений. Наш объект Symbol позволил нам добавить поддержку перекоса в Phaser.

Объединение символов — одна из добавленных нами оптимизаций. Мы хотели иметь возможность повторно использовать символ фильма для воспроизведения разных анимаций, а это означало, что при смене анимации некоторые символы больше не понадобятся. Вместо выделения и освобождения символов мы объединяем и повторно используем их, назначая им новые данные текстуры. Любой неиспользуемый символ остается в пуле до тех пор, пока он не понадобится.

Метки кадров

Одной из наиболее интересных функций Flump является возможность экспорта меток кадров с временной шкалы в Animate. Метка кадра — это просто строка, присвоенная ключевому кадру. Это полезно, потому что позволяет разработчикам прослушивать метки кадров для запуска внутриигровых событий. Например, если наши аниматоры создают анимацию заставки, они могут использовать метки кадров, чтобы сообщить игре, когда она должна начать воспроизведение голоса поверх аудио или звуковых эффектов. Метки кадров также можно использовать в коде, чтобы указать анимации воспроизводиться до тех пор, пока она не достигнет какой-либо метки, или перейти к определенной метке и остановиться на ней. Это была важная функция, чтобы убедиться, что мы перенесли ее в плагин.

movie.labelEvents.add((label) => {
    if (label === “playSfx”) {
        sound.play();
    }
});

С нашим объектом Symbol и пулом символов мы смогли перенести среду выполнения Flump в Phaser. В целом все прошло гладко. Мы обнаружили пару ошибок, которые мы исправили, и мы не столкнулись с какими-либо серьезными проблемами. После того, как все было сделано, у нас появился плагин анимации Flump для Phaser 2, который точно воспроизводил контент, созданный в Adobe Animate.

Контроль скорости

После того, как реализация Flump была завершена, мы обнаружили, что хотим иметь более высокий уровень контроля над воспроизведением. Хотя анимации воспроизводились и анимировались с правильной частотой кадров, мы хотели иметь возможность контролировать скорость воспроизведения анимации. Это позволило бы нам ускорять и замедлять анимацию в зависимости от игровой логики. Добавление этой функции было несложным, потому что требовалось только масштабирование дельта-времени, используемой для продвижения анимации.

Это действительно создавало проблему, когда анимация замедлялась. Они выглядели неуклюжими; как будто игра работала с более низкой частотой кадров, хотя она все еще работала со скоростью 60 кадров в секунду. Когда Flump продвигает анимацию, она округляет положение кадра. Это делается для того, чтобы не возникало ошибок при извлечении ключевых кадров из массива. Проблема в том, что когда дело дошло до расчета интерполяции между одним кадром и другим, он делал это целыми шагами. Итак, кадр с первого на второй, со второго на третий и так далее. Это хорошо для выяснения того, какие данные ключевого кадра использовать, однако это не работает для масштабирования скорости анимации. Чтобы исправить это, мы разрешили интерполяции использовать части кадров, не позволяя анимации воспроизводиться дальше ключевого кадра, на котором она находится в данный момент. Итак, если наш последний кадр был один, а наш следующий кадр был два, то, если игровое время определило, что мы на самом деле находимся в позиции кадра 1,5, тогда анимация будет использовать 1,5 для интерполяции между двумя кадрами. Мы по-прежнему использовали целые числа для определения позиций ключевых кадров, однако теперь анимация может использовать доли кадров для интерполяции. Результат — гораздо более плавная анимация. Они по-прежнему анимируются с частотой кадров, установленной в Adobe Animate, однако в нашем плагине они воспроизводятся более плавно. Эти более плавные анимации позволили нам масштабировать скорость воспроизведения, чтобы более медленные скорости не выглядели неуклюжими.

Вывод

После того, как мы смогли сгладить анимацию, плагин был готов. Нам удалось создать проигрыватель Flump для Phaser 2, который позволяет разработчикам повторно использовать ролики для нескольких анимаций, а также внедрить оптимизации и улучшения.

Вы можете найти исходный код плагина Phaser 2 Flump на GitHub здесь. Плагин также доступен на NPM здесь. Мы также предоставляем демонстрационный проект, который показывает примеры использования плагина здесь.

Что дальше?

В настоящее время мы переносим этот подключаемый модуль на Phaser 3. Хотя порт Flump для Phaser 2 был простым, Phaser 3 не поддерживает возможность наклона изображения. Поскольку Phaser 2 построен на основе PIXI, мы смогли легко использовать масштаб и значение перекоса Flump для расчета матрицы для определения поворота объекта. В Phaser 3 вычисления матриц отделены от средств визуализации и игровых объектов, что усложняет интеграцию с Flump. Когда мы, наконец, перенесем Flump на Phaser 3, мы хотим убедиться, что он полностью интегрирован в движок, чтобы обеспечить максимальную стабильность.