Компания
48,64
рейтинг
22 марта 2013 в 16:09

Разработка → Создание игровой анимации на примере Pudding Monsters



Всем привет!
Сегодня я расскажу, как мы упростили процесс создания анимации в играх, используя возможности Adobe Flash.

Каждый, кто сталкивался с созданием 2D анимации, знает, что существует как минимум два основных подхода — покадровая и программная анимация. Ни один из этих подходов не является приемлемым, если в мобильном приложении требуется сложная анимация какого-либо объекта. В первом случае получается огромный атлас текстур, который сложно уместить в ограниченную память устройства. В случае с программной анимацией художник и программист должны потратить кучу времени, чтобы захардкодить все трансформации. Такая анимация обычно получается упрощенной из-за сложности ручного переноса параметров трансформаций.

Так что же делать, если в приложении нужна красивая и сложная анимация? Правильно, нужно автоматизировать процесс создания программной анимации. Создание анимации необходимо полностью переложить на плечи художника, программист же должен заниматься написанием логики ее отображения.

Исторически сложилось, что Adobe Flash стал практически стандартом в области создания 2D анимации, а начиная с версии CS5, исходный файл с анимацией .fla — это обычный zip, внутри которого находится Flash документ в формате XFL. Именно его мы и используем для экспорта трансформаций на этапе подготовки ресурсов приложения.

Внутреннее устройство .fla файла

image
Не смотря на то, что документации по формату XFL до сих пор нет в открытом доступе, не составляет труда разобраться в его устройстве (об этом уже писали на хабре). Файл DOMDocument.xml содержит описание всех трансформаций с использованием символов из библиотеки (директория LIBRARY). Все остальное в нашем случае не потребуется.

Каждый ключевой кадр в файле DOMDocument.xml представлен следующим образом:

<DOMFrame acceleration="100" index="39" keyMode="22017" motionTweenSnap="true" tweenType="motion">
	<elements>
		<DOMSymbolInstance libraryItemName="body_2" loop="single frame" symbolType="graphic">
			<matrix>
				<Matrix a="0.999252" b="0.038650" c="-0.038665" d="0.999481" tx="441.15" ty="890.95"/>
			</matrix>
			<transformationPoint>
				<Point x="-2.4" y="33.6"/>
			</transformationPoint>
		</DOMSymbolInstance>
	</elements>
</DOMFrame>

Самая важная часть в этом представлении — атрибуты тега Matrix. Также здесь содержится информация о порядковом номере кадра, имени символа, центре трансформаций и типе перехода между кадрами.

Обработка данных

Для воспроизведения трансформаций на движке игры проводится декомпозиция матрицы трансформации. Чтобы получить значения наклона (skew) и масштаба (scale) по каждой оси координат, воспользуемся формулами:
skewX = atan(-c/d)
skewY = atan(b/a)
scaleX = sqrt(a2+b2)
scaleY = sqrt(c2+d2)

Ресурсы приложения

В ресурсы приложения после обработки попадает файл с описанием трансформаций с формате, понятном игровому движку. На основе этого файла (тоже XML, только без лишней информации) создается анимированный игровой объект. Программисту лишь требуется добавить его в правильное место на сцену и вызвать нужную анимацию.

Изображения, которые находятся внутри .fla файла, не используются во время отрисовки, а получаются из соответствующих слоев отдельных .psd файлов. Это позволяет использовать один .fla файл при создании анимации для нескольких разрешений. Организация библиотеки .fla файлов отражает эту зависимость:

image

Преимущества данного подхода

На примере продемонстрирую преимущества описанного метода, который был успешно опробован в нашей игре Pudding Monsters. Подсказки игроку реализованы в виде анимированных диалоговых пузырей, которых только в первом наборе уровней появляется 7 различных штук. Вот, как это выглядит в Adobe Flash:

image

Если бы мы пошли по простому пути и использовали покадровую анимацию, то кадры для каждой анимации подсказки разместились бы на атласе текстур с разрешением в среднем 4016x2086 (для экрана iPhone 4), например, на таком:

image

В результате, в памяти потребовалось бы держать порядка 16 МБ для каждой анимации, и это определенно перебор для такого второстепенного графического элемента. Пришлось бы упрощать анимацию и искать пути оптимизации.
image
С автоматизированным экспортом трансформаций, все что нужно для воспроизведения анимаций, — это атлас с разрешением 518x942 пикселей и файл с описанием объемом 284 КБ. Помимо того, что требуется так мало ресурсов, анимация проигрывается с частотой кадров 60 fps.

Такой подход позволил существенно уменьшить трудозатраты на создание анимации для всех наших игр, но это всего лишь один из вариантов автоматизации процесса.

Буду рад обсудить, как вы решали подобные задачи в своих проектах.
Автор: @skomik
ZeptoLab
рейтинг 48,64

Комментарии (29)

  • 0
    То есть с вашим подходом возможно экспортировать только растровые символы?
    • 0
      Да, это одно из ограничений на текущий момент.
      • +1
        Ясно. В моем проекте нужно было экспортировать в том числе и векторную анимацию, поэтому был написан простой парсер swf… Swf файлы экспортировались в спрайтшиты и простой xml или plist, структура у которого напоминала swf — очень ограниченный набор тегов. Настройка масштаба для разных разрешений легко производится во время экспорта.
  • +1
    А можно по-подробнее, о подготовке psd файла и атласа для движка. C флэшем всё ясно, послойный psd в качестве атласа. А в движке вы как реализовали такой же атлас? В каком-нить texture packer'e тот же psd редактировали под движок и в png?
    • 0
      Есть небольшой парсер формата PSD, умеющий вытаскивать слои и упаковывать их в атласы.
      • 0
        В Gimp я делаю это при помощи GMIC, Layers to Tiles
  • +1
    как вы решали подобные задачи в своих проектах.

    парсится swf, по ней генерируется спрайтшит, xml описания анимаций и код.

    За счет генерации кода есть возможность обращаться к частям анимации, изменять в рантайме ее свойства. Кроме того это упрощает работу с графикой.
    Можно делать так (весь код MyClip и его детей генерируется):

    var clip = new MyClip();
    clip.child1.partOfChild.Rotation = 40;
    clip.someOtherChild.GotoAndPlay(12);
    clip.FinishEvent += OnAnimationFinish;

    Код на C#, так как пишу на моно.
    • 0
      Не пойму в чем новизна подхода автора статьи.
      Эта техника давно уже используется.
      Вот пруф из недавнего:

      Added by Raymond Lu 4 months ago

      I create a tool named Super Animation Converter, which is a simple SWF (a file format supported by Adobe Flash Player software) converter. It can parse and extract transformation data from SWF file. With these transformation data and the right images, you can reproduce the animation in any game engine just as Adobe Flash Player can do.

      The native animation solution in Cocos2D game engine is “frame by frame” animation, which means if there are 20 frames in your animation, you need 20 pieces of image(texture), and draw these images one by one on the screen to create animation effect. There are two flaws in this solution:

      1 High resource consuming, one frame one image;
      2 Hard to make smooth animation, since no interpolation between frames, which means it “jumps” directly from the current frame to the next frame.

      So I try to provide a better animation solution which is based on Super Animation Converter for Cocos2D game engine. The idea is very simple:

      1 Use Flash as your animation editor, create any animation you want in it, then export these animation as SWF file.
      2 Parse the SWF file with Super Animation Converter, get the transformation data and images(NOT the whole frame) from the SWF file.
      3 Reproduce the animation in Cocos2D game engine with the transformation data and images.

      This project costs me lots of time.
      But since we are so close to the end of the world, I decide to share it with all of you guys.
      Please read «super_anim_help_english_version_1.pdf» first, then enjoy it!

      I’ve put the tool & source code in github:
      github.com/raymondlu/super-animation-samples

      Updates
      1 Support sprite sheet, which means you can use TexturePacker to pack some small images into one big images
      2 Support resize animation, you can resize one animation to different size to support multiple resolution
      3 Add set flip x&y function
      4 Fix some crash bugs, some depth bugs, alpha blend bugs, more stable now

      Enjoy it!

      www.cocos2d-x.org/boards/6/topics/19621?r=19711
      • 0
        Полностью с исходниками
        I’ve put the tool & source code in github:
        github.com/raymondlu/super-animation-samples
        • 0
          На новизну я и не претендовал. Видел реализацию, на которую вы ссылаетесь, исходники Super Animation Converter недоступны.
          • 0
            А зачем Вам исходники Super Animation Converter? Можно подумать, что Вам еще необходимы срочно исходники Adobe Flash или Adobe Photoshop только потому, что Вы используете эти инструменты. Имелись в виду исходники для встраивания в двиг.

            А Вы выложили исходники тулзы на паблик?

            Если нет, в чем преимущество Вашего решения по сравнению с приведенным мной примером?
  • +2
    Как вы делаете скейлинг лэйаута интерфейса для разных разрешений?
    • 0
      Привязываем объекты интерфейса к различным опорным точкам, углам экрана, например. В двух словах не объяснить, это тема для отдельной статьи.
  • 0
    Немного не понял. А можно еще раз на примере? Вот есть такой объект — резиновый прямоугольник. И его анимация, левая часть объекта уходит вниз, правая — вверх, а середина остается на месте. Я хорошо себе представляю, как это анимируется во флеше. Но каким образом, можно провести такую трансформацию над растровым спрайтом, который ложится на полигон из 2ух треугольников?

    image
    • 0
      Двигаете вершины треугольников и все.
    • 0
      Обычная трансформация, shear называется вроде.
      • 0
        Also 2 soulburner. Я немного про другое говорю. 1 — это исходный резиновый кирпич на полигоне. 2 — то, что получиться с помощью shear (правые вертексы вверх, левые вниз). 3 — то что нужно и очевидно невозможно получить, простыми трансформациями.

        • 0
          Так и 3-й вариант вы и во флеше без векторного морфа не получите.
          • 0
            Собственно, этот вопрос у меня потому и появился. Я в принципе не мог себе представить, что вообще все анимации в Pudding Monsters это тупо skew и scale. Для меня это выглядело настоящим вектором. И только сейчас, с лупой посидев над айфоном, вижу отдельные спрайты. Нереально крутая работа)
            • 0
              а еще таким же образом анимируется зелененький Om-nom из Cut the Rope. Шедевр!
              • 0
                Om Nom вообще покадровый :-)
                • 0
                  пруф! :)

                  Не могу, конечно, утверждать, что он не покадровый, т.к. это мое предположение.
                  И раньше тоже думал, что он покадровый, но присмотревшись под лупой… :)
                  • 0
                    Для Android APK-файлы не зашифрованы, достаточно заглянуть в папку assets на png файлы :-) В случае iOS примерно так же.
  • 0
    Отличный подход! А есть ли его opensource реализация для javascript?
    • 0
      Не встречал.
  • +1
    Расскажите немного подробней. Есть у вас векторная анимация в fla файле. Как она воспроизводится в iOS? Приложение полностью создается во Flash Builder-e или у вас есть какой-то свой компонент, который воспроизводит такие анимации?

    Магия рук между атласом 4016х2086 и атласом 518х942 для меня также осталась загадкой. :)
    • 0
      Есть у вас векторная анимация в fla файле

      Есть анимация с растровыми символами во fla файле.

      Как она воспроизводится в iOS?

      Игровым движком, написанном на C++, средствами OpenGL.

      Приложение полностью создается во Flash Builder-e или у вас есть какой-то свой компонент, который воспроизводит такие анимации?

      Flash Builder не используется. Как воспроизводятся анимации, я ответил выше.

      Магия рук между атласом 4016х2086 и атласом 518х942 для меня также осталась загадкой. :)

      Каждый ключевой кадр не хранится полностью на атласе, а собирается по кусочкам, никакой магии :). Это становится понятнее, если присмотреться к последним двум скриншотам.
      • 0
        Спасибо за детальный ответ. Стало много яснее. :) Хорошие у вас аниматоры, раз рисуют такую красоту из статических картинок используя пару трансформов.
  • 0
    Тут было сообщение которое отправилось повторно по ошибке.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.

Самое читаемое Разработка