С точки зрения графики большинство инди-игр завоевывают свою популярность не количеством полигонов в кадре или супер-качеством текстур, а необычным подходом к арту и вниманием к мелочам, причем большинство использует только 2D графику. На мой взгляд, для проектов в таком стиле отлично подходит Flash. Под флешем в данном случае следует понимать не только плагин для браузеров, который постепенно сдает свои позиции и уступает место HTML5, а саму “эко-систему”, которая позволяет использовать возможности и “идеологию” флеша для разработки под десктоп и мобильные платформы. Речь пойдет об Adobe AIR (кроссплатформенная среда для запуска приложений) и фреймворке Starling, используeмых в разработке инди игры.
Под катом — примеры практических решений и анимации эффектов.
Проект представляет собой продвинутый порт некогда популярной флеш-игры для Steam, разумеется, в расширенном виде (например, число уровней увеличилось с 30 до 200+), и многие “подводные камни” пришлось обходить заново, уже на другой платформе.
В изначальной флеш игре использовалась растеризация контента при старте приложения(точнее, при первом переходе из главного меню на экран выбора уровень). Каждый кадр из каждого MovieClip’а сохранялся в отдельном объекте BitmapData. Разумеется, решение было очень “топорным”, но для простой флеш игры подходило неплохо.
В варианте игры для Steam (а впоследствии, возможно, и для мобильных платформ) этот вариант не подходит по двум причинам:
1. Большой объем занимаемой памяти после растеризации. Данные в MovieClip в Starling передаются через массив текстур. Текстура может быть не только загружена из файла, но создана с использованием данных из BitmapData. Правда, таком случае стоит помнить, что Starling (точнее, stage3D, на котором он построен) использует текстуры высотой и шириной равной степени двойки. Т.е. изображение размером 130x160 пикселей будет иметь “размер” в памяти равный 256x256.
2. Еще один минус — большое количество draw call’ов. К счастью, в Starling есть автоматический батчинг изображений (вывод нескольких спрайтов за одно обращение к графическому API), если они находятся внутри одной текстуры.
Решение проблемы: использование текстурных атласов.
Первоначально планировался вариант генерации атласов “на лету”, используя DynamicTextureAtlas, а вся графика игры хранилась бы в векторном виде.
После тестового запуска выяснилось, что ресурсы flash-игры (в виде swc — библиотеки классов с закрытым исходным кодом) должны иметь четко определенную структуру, что не подходило для уже имеющихся наработок. Также выяснилось, что преобразование вектора в растр (по сути — отрисовка каждого объекта покадрово, причем именно средствами Flash) занимает достаточно много времени, и, чем больше был размер объекта в игре, тем больше времени занимала растеризация (понятно, что размеры всех элементов в пикселях для экранов разрешением 800x480 и 1920x1080 будут отличаться в разы).
По сути, это убивало все плюсы использования векторной графики, а именно — масштабируемость без потери качества. Выход был один, классический — использование заранее созданных текстурных атласов.
После сохранения всей графики в виде png файлов и создания атласов выяснилось, что порядка 70% места занимают кадры различных эффектов, причем зачастую достаточно простых. Решение проблемы было очевидно — замена объемных анимаций (преобразованных из вектора) в анимации, созданные из составных частей. Это дает существенную экономию места, т.к., скажем, эффект взрыва звезды(показан ниже), сохраненный покадрово и помещенный в атлас, занимал бы текстуру размером 1024x1024 пикселей, которая бы заняла бы в памяти 4 Мб, тогда как составные части анимации суммарно занимают не больше 128x128 пикселей.
Пример части текстурного атласа с отдельными кадрами анимации:
![](https://habrastorage.org/r/w1560/files/22a/fd5/899/22afd58996c74b13955d501b8ce0519f.png)
И составные части эффектов:
![](https://habrastorage.org/r/w1560/files/188/a20/b21/188a20b21f4841049efd22004e2d01d4.png)
Изначально я планировал использовать базовое расширение для Starling (Particle System), но после сбора тестового проекта обнаружился ряд вещей:
1. Даже самый богатый выбор настроек не дает того, что можно самому изменить в коде. Например, формулу изменения скорости полета частицы.
2. Редактор “заточен” в первую очередь на реалистичный показ постоянных источников частиц. Пример — пламя горящей свечи. В нашей же игре большинство эффектов по сути являются взрывами.
Пример эффекта из редактора Particle System:
![](https://habrastorage.org/r/w1560/files/8e2/165/e58/8e2165e584ec44f19f6d7c7bc46303e8.png)
В итоге было решено использовать самописный редактор эффектов.
Плюсы — возможность подключать не только систему частиц, но и добавить спрайты-подложки с изменяемыми скейлом, скорость поворота и альфой, а набор параметров создан исходя из желаний дизайнера. Каждый из эффектов состоял из нескольких слоев. 3 нижних слоя — для отдельных спрайтов, которые меняют свой скейл, угол поворота и прозрачность. 3 верхних — для партиклов, как правило — разлетающихся из одной точки.
![](https://habrastorage.org/r/w1560/files/ac4/e05/c54/ac4e05c54c494e3d9853c8b27b9dddcc.png)
Примеры эффектов
Сравнение эффектов из флеш-версии и сделанных в редакторе:
1. Анимация взрыва (слева — флеш версия):
![](https://habrastorage.org/files/e29/e0e/0c1/e29e0e0c1cc042c197166049e7e4b8e2.gif)
2. Анимация взятия объекта (звезды), слева — флеш:
![](https://habrastorage.org/files/cfd/691/02e/cfd69102ef81442facde850e275ebe16.gif)
Отдельным плюсом версии с частицами является настраиваемый элемент случайности — каждый взрыв/эффект (одного типа) выглядит по разному, т.к. число частиц, их размер и скорость варьировались в определенных пределах, задаваемых в редакторе.
Еще один плюс работы со Starling’ом — доступные “из коробки” эффекты обработки изображений. Данные эффекты в игре используются в нескольких местах, например, после выигрыша и появления меню результатов сам фон уровня (и оставшиеся на нем объекты) постепенно меняются.
Первоначально мы, так же как и во флеш-версии, хотели сделать эффект, когда картинка уровня постепенно “заблюривается”, вращаясь по часовой стрелке (все это идет “фоном”, под меню результатов уровня). Но в версии со Starling использование этого эффекта очень резко уменьшало fps, даже в PC-версии игры (с 50-60 до 2-3 кадров в секунду).
![](https://habrastorage.org/r/w1560/files/3a5/383/ad4/3a5383ad41064ffbb26288f580d9c4c2.png)
Вместо этого было решено использовать эффект «выцветания» (идет “змейкой” слева направо и сверху вниз по элементам), изменяя прозрачность объекта и данные матрицы фильтра ColorMatrixFilter, что позволило сделать достаточно зрелищный эффект без просадки fps.
![](https://habrastorage.org/r/w1560/files/c43/bd9/3c9/c43bd93c945b481db0cc80da64cc537b.png)
В заключение могу сказать, что вся эко-система Flash позволяет дизайнеру и программисту «общаться на одном языке» при создании и полировке графики, что позволяет уделять больше внимания мелочам, которые и создают атмосферу игры, а проблемы с производительностью, возникающие при «топорных» решениях, заставляют искать обходные пути и иногда изменять некоторые концепции, что часто идет на пользу конечному продукту.
Под катом — примеры практических решений и анимации эффектов.
Из вектора в растр
Проект представляет собой продвинутый порт некогда популярной флеш-игры для Steam, разумеется, в расширенном виде (например, число уровней увеличилось с 30 до 200+), и многие “подводные камни” пришлось обходить заново, уже на другой платформе.
В изначальной флеш игре использовалась растеризация контента при старте приложения(точнее, при первом переходе из главного меню на экран выбора уровень). Каждый кадр из каждого MovieClip’а сохранялся в отдельном объекте BitmapData. Разумеется, решение было очень “топорным”, но для простой флеш игры подходило неплохо.
В варианте игры для Steam (а впоследствии, возможно, и для мобильных платформ) этот вариант не подходит по двум причинам:
1. Большой объем занимаемой памяти после растеризации. Данные в MovieClip в Starling передаются через массив текстур. Текстура может быть не только загружена из файла, но создана с использованием данных из BitmapData. Правда, таком случае стоит помнить, что Starling (точнее, stage3D, на котором он построен) использует текстуры высотой и шириной равной степени двойки. Т.е. изображение размером 130x160 пикселей будет иметь “размер” в памяти равный 256x256.
2. Еще один минус — большое количество draw call’ов. К счастью, в Starling есть автоматический батчинг изображений (вывод нескольких спрайтов за одно обращение к графическому API), если они находятся внутри одной текстуры.
Решение проблемы: использование текстурных атласов.
Первоначально планировался вариант генерации атласов “на лету”, используя DynamicTextureAtlas, а вся графика игры хранилась бы в векторном виде.
После тестового запуска выяснилось, что ресурсы flash-игры (в виде swc — библиотеки классов с закрытым исходным кодом) должны иметь четко определенную структуру, что не подходило для уже имеющихся наработок. Также выяснилось, что преобразование вектора в растр (по сути — отрисовка каждого объекта покадрово, причем именно средствами Flash) занимает достаточно много времени, и, чем больше был размер объекта в игре, тем больше времени занимала растеризация (понятно, что размеры всех элементов в пикселях для экранов разрешением 800x480 и 1920x1080 будут отличаться в разы).
По сути, это убивало все плюсы использования векторной графики, а именно — масштабируемость без потери качества. Выход был один, классический — использование заранее созданных текстурных атласов.
От анимации — к частицам
После сохранения всей графики в виде png файлов и создания атласов выяснилось, что порядка 70% места занимают кадры различных эффектов, причем зачастую достаточно простых. Решение проблемы было очевидно — замена объемных анимаций (преобразованных из вектора) в анимации, созданные из составных частей. Это дает существенную экономию места, т.к., скажем, эффект взрыва звезды(показан ниже), сохраненный покадрово и помещенный в атлас, занимал бы текстуру размером 1024x1024 пикселей, которая бы заняла бы в памяти 4 Мб, тогда как составные части анимации суммарно занимают не больше 128x128 пикселей.
Пример части текстурного атласа с отдельными кадрами анимации:
![](https://habrastorage.org/files/22a/fd5/899/22afd58996c74b13955d501b8ce0519f.png)
И составные части эффектов:
![](https://habrastorage.org/files/653/236/cae/653236cae0a840d390567ae991ace855.png)
![](https://habrastorage.org/files/188/a20/b21/188a20b21f4841049efd22004e2d01d4.png)
Создание редактора частиц
Изначально я планировал использовать базовое расширение для Starling (Particle System), но после сбора тестового проекта обнаружился ряд вещей:
1. Даже самый богатый выбор настроек не дает того, что можно самому изменить в коде. Например, формулу изменения скорости полета частицы.
2. Редактор “заточен” в первую очередь на реалистичный показ постоянных источников частиц. Пример — пламя горящей свечи. В нашей же игре большинство эффектов по сути являются взрывами.
Пример эффекта из редактора Particle System:
![](https://habrastorage.org/files/8e2/165/e58/8e2165e584ec44f19f6d7c7bc46303e8.png)
В итоге было решено использовать самописный редактор эффектов.
Плюсы — возможность подключать не только систему частиц, но и добавить спрайты-подложки с изменяемыми скейлом, скорость поворота и альфой, а набор параметров создан исходя из желаний дизайнера. Каждый из эффектов состоял из нескольких слоев. 3 нижних слоя — для отдельных спрайтов, которые меняют свой скейл, угол поворота и прозрачность. 3 верхних — для партиклов, как правило — разлетающихся из одной точки.
![](https://habrastorage.org/files/ac4/e05/c54/ac4e05c54c494e3d9853c8b27b9dddcc.png)
Примеры эффектов
Сравнение эффектов из флеш-версии и сделанных в редакторе:
1. Анимация взрыва (слева — флеш версия):
![](https://habrastorage.org/files/27c/d61/30e/27cd6130e44b45948126d3bdcbc688fd.gif)
![](https://habrastorage.org/files/e29/e0e/0c1/e29e0e0c1cc042c197166049e7e4b8e2.gif)
2. Анимация взятия объекта (звезды), слева — флеш:
![](https://habrastorage.org/files/fc3/7c1/c6a/fc37c1c6a5704b4cb99b7909edc53456.gif)
![](https://habrastorage.org/files/cfd/691/02e/cfd69102ef81442facde850e275ebe16.gif)
Отдельным плюсом версии с частицами является настраиваемый элемент случайности — каждый взрыв/эффект (одного типа) выглядит по разному, т.к. число частиц, их размер и скорость варьировались в определенных пределах, задаваемых в редакторе.
Эффекты обработки изображений
Еще один плюс работы со Starling’ом — доступные “из коробки” эффекты обработки изображений. Данные эффекты в игре используются в нескольких местах, например, после выигрыша и появления меню результатов сам фон уровня (и оставшиеся на нем объекты) постепенно меняются.
Первоначально мы, так же как и во флеш-версии, хотели сделать эффект, когда картинка уровня постепенно “заблюривается”, вращаясь по часовой стрелке (все это идет “фоном”, под меню результатов уровня). Но в версии со Starling использование этого эффекта очень резко уменьшало fps, даже в PC-версии игры (с 50-60 до 2-3 кадров в секунду).
![](https://habrastorage.org/files/3a5/383/ad4/3a5383ad41064ffbb26288f580d9c4c2.png)
Вместо этого было решено использовать эффект «выцветания» (идет “змейкой” слева направо и сверху вниз по элементам), изменяя прозрачность объекта и данные матрицы фильтра ColorMatrixFilter, что позволило сделать достаточно зрелищный эффект без просадки fps.
![](https://habrastorage.org/files/c43/bd9/3c9/c43bd93c945b481db0cc80da64cc537b.png)
Выводы
В заключение могу сказать, что вся эко-система Flash позволяет дизайнеру и программисту «общаться на одном языке» при создании и полировке графики, что позволяет уделять больше внимания мелочам, которые и создают атмосферу игры, а проблемы с производительностью, возникающие при «топорных» решениях, заставляют искать обходные пути и иногда изменять некоторые концепции, что часто идет на пользу конечному продукту.