Показаны сообщения с ярлыком flixel. Показать все сообщения
Показаны сообщения с ярлыком flixel. Показать все сообщения

воскресенье, 29 июля 2012 г.

NME и HTML5: ready or not?

Прежде всего хочу сказать, что все изложенное в данном сообщении является итогом двухдневного "экспериментрирования", и может не отражать действительного положения дел. Если я ошибаюсь, то прошу меня поправить и посоветовать эффективные техники использования Jeash.

В начале этой недели я в очередной раз попытался скомпилировать простую демку для HaxeFlixel в html5 и сразу же наткнулся на проблему: метод draw() класса BitmapData не учитывал параметры matrix (трансформация положения и формы) и colorTransform (цветовая трансформация), в то время как отрисовка графики в движке полностью строится на двух методах (draw() и copyPixels()). Но за что я люблю NME, так это за отзывчивость разработчиков, и буквально за три дня описанная проблема была исправлена. После этого я занялся непосредственно попыткой скомпилировать демку FlxInvaders в js-код. Сам процесс занял около 6 часов и состоял в основном в дописании параметров условной компиляции (ничего сложного), сам код практически не изменился. И вот, наконец, мне удалось запустить ее, но результат не впечатлил: всего 15-16 фпс против желаемых 30.
После этого началось небольшое исследование + экспериментрирование:
  • где-то полгода назад я услышал о Jangaroo -- специальном SDK, позволяющем компилировать AS3-код в JS, примерно тогда же встретил демку Jumper -- платформер, написанный на AS3 с использованием Flixel и портированный с помощью Jangaroo на html5. То есть успешные попытки портирования Flixel на html5 уже есть, и довольно давно. Так вот, вспомнив об этой технологии, решил поискать еще примеров по ней. Гугл выдал мне следующую страницу, содержащую несколько ссылок по данному предмету, в том числе и на демку FlxInvaders, которая у меня в Хроме выдает в среднем 42-43 фпс, т.е. почти в три раза быстрее.
  • увидев такую разницу в производительности, у меня возникло две мысли: а) мой порт тормозной и б) Jeash тормозной. С первой я спорить не стану, т.к. Flixel использует отрисовку всей графики в одну битмапдату (что является аналогом использования только одного элемента Canvas в JS), а это не самая эффективная техника (но Jangaroo умудряется выдавать при этом гораздо лучший результат), то вторая требовала более подробного изучения.
  • и один день я посвятил данному вопросу. Написал несколько пару простых демок, суть их такова: имеем приложение размером 800х600, в него рисуются спрайты, в каждый из которых вложена битмапа с одним и тем же изображением (30х30 px). В итоге имеем, что при 30 фпс я могу отрисовать 110-120 таких спрайтов, а при 60 — только 45. И это в Хроме, в ФайрФоксе и IE все хуже. Мне такие результаты совсем не нравятся, и Jeash (я так считаю) еще не готов для написания "серьезных" игр (под серьезными здесь я понимаю игры с большим количеством движущихся и трансформируемых объектов).
В итоге родилась следующая, так сказать, "мысль": переписать под себя класс BitmapData (ориентируясь на его текущую реализацию и версию Jangaroo), т.к. практически весь вывод графики в HaxeFlixel зависит от него. Но это, опять же, в отдаленной перспективе, т.к. в приоритете система слоев для C++, которая все так же находится в ранней стадии разработки, а затем stage3D-версия.

UPD: Совершенно забыл приложить скомпилированную версию демки и исходники теста производительности отрисовки спрайтов

суббота, 7 июля 2012 г.

HaxeFlixel 1.05

С момента записи о планах на версию 1.02 прошло уже два месяца. За это время успело выйти несколько обновлений, о которых я, к сожалению, не писал, а сегодня вышла 1.05. Что же мы имеем на текущий момент:
- все, что было запланировано для версии 1.02;
- исправлено несколько ошибок (самой важной из которых считаю исправление работы звука под android);
- классу FlxSprite добавлен метод loadFrom(), позволяющий использовать в текущем спрайте графику из другого спрайта. Этот метод является еще одним шагом к решению проблемы порядка отрисовки графики. О дальнейшем ходе возможного решения данной проблемы напишу чуть позже в этом посте;
- интрегрирована система tween-анимации из HaxePunk -- теперь у всех подклассов FlxBasic доступны методы addTween(), removeTween() и clearTweens(), а также у класса FlxG появилось статическое свойство tweener, которое может использоваться как глобальный инструмент для анимации. Базовым классом для таких анимаций является класс org.flixel.tweens.FlxTween (в оригинале назывался просто Tween), его возможные вариации (подклассы) находятся в пакетах org.flixel.tweens.*. Для справки о применении tween-анимаций посмею направить вас изучать соответствующие туториалы FlashPunk'а. Если же кому-нибудь будет интересно рассмотреть данный вопрос отдельно, то пишите о этом в комментариях
- добавлена базовая поддержка мультитача и джойстиков. Джойстики поддерживаются только на c++ и толком еще не тестировались, поэтому мне нужна ваша помощь в этом деле (опять же заинтересовавшихся прошу писать в комменты -- тестовый пример вышлю);
- поддержка новой версии языка Haxe 2.10. На самом деле я еще не совсем уверен, что закончил ее, т.к. иногда приложение вылетает с ошибкой, но эта проблема может быть вызвана еще и нестабильностью SVN-версии HXCPP и возможной неполной совместимостью с NME. Так что здесь надо будет подождать их официального выхода, там посмотрим.
Об остальных менее важных изменениях можно прочитать в списке изменений.
Теперь о дальнейших планах. Если вы иногда просматриваете список текущих проблем на ГитХабе, то уже сами все знаете:
- решение проблемы порядка отрисовки графики для c++. Здесь, я думаю, поможет использование текстурных атласов, о реализации которых я писал в одном из предыдущих постов, а также внедрение идеи "слоев", когда у каждого из слоев будет свой атлас. В каждом из таких атласов может находиться одно или несколько изображений для спрайтов и прочих графических классов (их будет нужно добавлять на этапе создания текущего стейта). Сам класс слоя будет подклассом FlxGroup (я думаю дать ему имя FlxLayer). Таким образом, спрайты в слое будут отрисовываться в таком же порядке, как они находятся внутри группы (их порядок в группе можно менять), также можно будет менять порядок отрисовки слоев. Графика в каждом слое будет отрисовываться за один присест. Такая "концепция" может помочь уменьшить вызов операций отрисовки графики, но также может иметь и отрицательные стороны, например, повышенное использование графической памяти.
- о создании stage3d версии я все еще думаю, но теперь мне эта идея не кажется такой простой. Так что ее вы увидите еще не скоро.
- также все чаще думаю о поддержке платформы html5, но пока что особых успехов не достиг. Буду пробовать дальше после выхода новой версии NME.
- добавление новых фич классу FlxTilemap, например, поддержки масштабирования (данная фича может быть полезна для использования тайловой карты в качестве фона)
- портирование экспортеров из редактора карт Dame для их использования с HaxeFlixel. Это должно облегчить создание уровней для игр, не прибегая каждый раз к ручному редактированию классов, получившихся на выходе из редактора.
- создание github-сайта для проекта, но эта идея пока что из разряда мечтаний.
- доработка поддержки мультитача -- касается классов, поддерживающих события мыши (FlxButton, FlxExtendedSprite и др.).
- небольшая кучка других изменений / "улучшений".
Как видно работы еще полно, этого развлечения мне надолго хватит. Ежели вам захочется увидеть реализованной какую-либо еще фичу, прошу запостить ее все там же или написать о ней в комментариях здесь.
На этом смею закончить. Надеюсь, в следующий раз напишу что-нибудь поинтереснее.

Обновление компонента BitmapFont

Наконец-то у меня дошли руки до доработки компонента для работы с растровыми шрифтами. Итак, что же нового было добавлено:
- самое главное изменение -- это добавление поддержки широко распространенного формата AngelCode. А самое важное это то, что для создания шрифтов в таком формате существует ряд специализированных программ (так что добавление нового шрифта значительно упрощается). Самой простой из них является BMFont (бесплатная, работает под Windows), позволяющий создавать шрифты на основе установленных в системе. К сожалению, настроек внешнего вида шрифтов в ней "кот наплакал" (размер, толшина обводки, сглаживание, использовать ли курсив или полужирное начертание), но это лучше чем ничего. Есть еще гораздо более продвинутая программа под Mac OS - Glyph Designer, но за нее просят порядка 30 американских президентов. Эти программы наиболее распространенные, но можно найти и другие.
- вторым, но уже совсем небольшим, изменением является добавление опции "useColor" (для AS3-blit и Haxe версий), или "useTextColor" (для AS3-Flixel версии) объектам класса PxTextField. Данное свойство имеет смысл использовать, если вы загружаете шрифт, созданный в программе Glyph Designer. Дело в том, что в этой программе есть возможность задавать основной цвет символов шрифта, а также задавать его обводку другим цветом. Но если загрузить такой шрифт в мой компонент когда свойство "useColor" имеет значение "true" (устанавливается по-умолчанию), то цвет шрифта будет трансформирован в соответствии со значением свойства "color" объекта PxTextField. Установив значение свойства "useColor" в "false", такой трансформации происходить не будет и шрифт будет выглядеть так, как вы это настраивали в программе.
- Так как в описываемый компонент была добавлена поддержка нового формата, то пришлось изменить немного способ работы со шрифтами. Если раньше, чтобы создать шрифт, нужно было писать код подобный следующему:
_font = new PxBitmapFont(fontBitmapData, fontString);
то теперь, в зависимости от того, в каком формате загружается шрифт, используется следующий синтаксис:
_font = new PxBitmapFont().loadPixelizer(fontBitmapData, fontString); // для загрузки шрифта в старом формате, взятом из движка Pixelizer,
или
_font = new PxBitmapFont().loadAngelCode(fontBitmapData, xmlFontData); // для загрузки шрифта в формате AngelCode, где xmlFontData -- XML данные шрифта.
(Если что-то непонятно, то рекомендую посмотреть пример, там все предельно просто и понятно)

В заключение хочу обратить внимание, что поддержка формата AngelCode в компоненте имеет некоторые ограничения / накладывает некоторые требования:
- как видно из используемого синтаксиса, все символы встраиваемого шрифта должны быть в одном графическом файле;
- поддерживается только xml формат *.fnt файлов (как самый простой для разбора);
- если вы планируете использовать свойство "color / textColor" для цветовой трансформации текста, то в опциях эспорта шрифта используйте опцию "White text with alpha" ("Белый текст с програчным фоном").


Теперь о дальнейших планах:
- планирую добавить поддержку "типов" текстовых полей. Думаю, что будет два типа -- динамические (как сейчас) и поля ввода. За основу возьму эту серию уроков по созданию компонентов для FlashPunk.
- возможно, что сделаю поддержку stage3D, но это в крайне отдаленной перспективе, т.к. еще очень много планов по развитию HaxeFlixel, но о них в следующий раз.
На этом все. До скорых встреч :)


P.S.: скачать компонент BitmapFont вы можете с github-репозитория "проекта"

воскресенье, 20 мая 2012 г.

Отчет за первую половину мая 2012

В предыдущем сообщении я писал о планах на следующий релиз HaxeFlixel. А спустя две недели, наконец, доделал все что планировалось. Дата официального релиза на haxelib пока остается открытой, так как для работы новой версии требуются новые фишки класса TileSheet из библиотеки NME, присутствующие только в SVN-версии. Так что ждем выхода следующей версии NME. А пока что для использования новой версии придется самостоятельно компилировать NME (инструкцию по компиляции можно найти здесь)
Теперь же собираюсь заняться переводом flash-версии Flixel на Stage3D. При работе буду ориентироваться на axel2d, благо что его структура практически совпадает со структурой Flixel. Еще одним инструментом будет портированный на Haxe ассемблер AGAL'а -- наконец-то без ошибок!!!

Следующей новостью является обновление движка Pixelizer до версии 0.4.3 (в основном содержит исправления ошибок). Haxe-порт был обновлен в тот же вечер, что и релиз, и лежит здесь. На него тоже есть некоторые планы -- добавление рендерера на основе класса TileSheet для нативных платформ.

И заметка для себя: покопаться с библиотекой nme-tilelayer от Philippe Elsass -- это обертка для класса TileSheet, предоставляющая базовые методы для работы со списком отображения (display-list), анимациями и трансформациями тайлов. Кроме нативных платформ, она работает на Flash и HTML5 (для этого используются битмапы). Пример использования -- nme-runnermark -- портированный с AS3 на Haxe бенчмарк производительности stage3d-фреймворков (результаты впечатляют).

пятница, 11 мая 2012 г.

Flixel for Monkey

В этом коротком сообщении хотелось бы рассказать о существовании проекта Flixel for Monkey. Это порт многократно здесь упоминаемого движка Flixel на язык Monkey. О том, что это за язык, вы можете узнать из статьи "О Monkey, откровенно" (автор этой статьи как раз и занимается данным портом). Я хотел бы поблагодарить его за проделанную им работу и за его советы по оптимизации движка. Как оказалось, процесс обнаружения и разрешения столкновений в оригинальном Flixel'e требует некоторой оптимизации -- в классах FlxQuadTree и FlxObject  создается много мусора (объектов типа FlxQuadTree, FlxList и FlxRect), что повышает потребление памяти приложением. Решение данной проблемы простое: кеширование и повторное использование объектов вместо создания новых. Пользуясь этой наводкой, а также сверяясь с исходным кодом порта (синтаксис языка Monkey оказался очень простым и понятным), описанная проблема была решена.
Еще раз хочу сказать спасибо товарищу Devolonter и надеюсь, что он не бросит свою работу.

воскресенье, 6 мая 2012 г.

Планы для версии HaxeFlixel 1.02

На прошлой неделе вышло обновление порта Flixel на haxelib до версии 1.01. Основными изменениями в данном релизе были портирование прелоадера (наконец-то) и совместимость с Haxe 2.09.  А сейчас я хотел бы поделиться планами на будущий релиз:
  1. В оригинальной версии движка поддерживается неоднородное масштабирование спрайтов, т.е. спрайту можно задать один масштаб по оси x и другой по оси y. При создании специального рендерера (для C++) на основе класса TileSheet пришлось отказаться от такой фичи, т.к. данный класс поддерживал только однородное масштабирование. Недавно такой функционал был добавлен (пока что только в SVN-репозитории библиотеки), причем теперь можно задавать не просто масштабные коэффициенты и угол поворота каждого тайла, а значения коэффициентов матрицы трансформации, т.е. мы можем еще и зеркально отразить тайл, скосить (skew) его, или совместить все эти трансформации вместе. Пользуясь новым функционалом я хочу вернуть неоднородное масштабирование, а также заново реализовать зеркальное отражение спрайтов (свойство flipped), которое сейчас реализовано путем изменения исходного изображения для спрайта.
  2. В текущей версии движка для C++ наблюдаются проблемы с отрисовкой спрайтов -- для повернутых или масштабированных спрайтов появляются графические артефакты. Эта проблема может быть решена простой модификацией изображения для спрайта -- вставкой "пустых" пикселей между изображениями кадров.
  3. Как я уже писал в предыдущем сообщении, реализация класса FlxText довольно неудачна для C++, и я начал работу над компонентом для работы с растровыми шрифтами. Текущая версия данного компонента для HaxeFlixel пока что работает только на Flash и уже лежит на гитхабе (класс FlxBitmapTextField), остается только реализовать отрисовку на C++ (с этим не должно возникнуть особых сложностей, т.к. подобную задачу я уже решал).
  4. "Улучшение" класса FlxButton. Может быть достигнуто заменой кода, отвечающего за отрисовку текста на кнопке, т.к. сейчас он выводится с помощью класса FlxText, это можно исправить используя разрабатываемый класс FlxBitmapTextField (хотя данное изменение еще под вопросом).
  5. Закончить портирование класса FlxBar (нужен, например, для отрисовки полоски здоровья у героя или врагов) из библиотеки Flixel Power Tools. Хотя данный класс и работает на всех поддерживаемых платформах, есть необходимость его оптимизации для C++, т.к. каждый раз при изменении отображаемого значения создается много мусора, что значительно замедляет работу приложения.
  6. Небольшой рефакторинг: замена объектов типа Dynamic на соответствующие типизированные объекты (там, где это возможно). Например, у кнопок есть свойство onUp, представляющее собой функцию, вызываемую при отпускании левой кнопки мыши, данное свойство должно вместо Dynamic быть Void->Void, т.е. быть функцией без аргументов и возвращаемого значения.
Вот и все планы на следующий релиз (на данный момент). Жду ваших предложений и всегда готов обсудить их в комментариях.

 

 

четверг, 3 мая 2012 г.

Компонент для работы с растровыми шрифтами

Продолжая работу над портом движка Flixel на Haxe, столкнулся с необходимостью оптимизации работы с текстом. Проблема заключается в следующем: стандартный класс движка FlxText сильно завязан на использование метода draw(), и при обновлении текста создается новый экземпляр класса BitmapData, еще одним недостатком является то, что для каждого такого текстового объекта создается свой экземпляр класса TileSheet (если в качестве целевой платформы установлен c++, neko или android). В общем видно, что такая реализация класса для отображения текста довольно неудачна и нужно искать другие решения. И тут на сцену выходят растровые шрифты -- каждый символ такого шрифта представляет собой по-сути простое изображение и работать с ними можно точно также, как и с обыкновенными изображениями. В наборе классов Flixel Power Tools как раз есть такой класс FlxBitmapFont и я его уже давно портировал, но в нем также присутствует довольно раздражающее меня ограничение -- он поддерживает только моноширинные шрифты (все символы таких шрифтов должны иметь одинаковую ширину), а мне же хотелось чего-нибудь более универсального. И недавно мне на глаза попался движок Pixelizer (упоминал его в одном из предыдущих сообщений), в котором очень понравилась реализация такого компонента: в нем уже был такой функционал, как изменение цвета шрифта, обводка и тени, поддержка многострочного текста и др. Встала задача по переводу этого добра на другие рельсы:
  1. Реализация в виде отдельного компонента, не завязанного ни на какой из движков -- такой класс нужен был для того, чтобы наконец-то закончить портирование прелоадера Flixel.
  2. Реализация в виде плагина для Flixel, которую можно использовать непосредственно в играх.
Самая первая версия порта была готова через 1-2 дня, но сразу же вылезли проблемы с производительностью: для отрисовки текста использовался метод draw(), позволяющий задавать тексту цветовую трансформацию и прочие параметры. Нужно было искать другой способ отрисовки. Подумав немного и посмотрев на реализацию спрайтов в Flixel, пришел к следующему решению: на входе имеем набор растровых изображений, представляющих собой исходные изображения символов растрового шрифта, а для того, чтобы отображать масштабированный и "окрашенный" текст создается дополнительный массив трансформированных изображений символов, таким образом, мы можем использовать уже гораздо быстрый метод copyPixels() (после такого преобразования нагрузка на процессор при отрисовке текста снизилась в 2-4 раза).
Завершив с оптимизацией, я приступил к реализации дополнительных "фишек":
  • настройка размера шрифта
  • настройка расстояний как между символами, так и между строками текста
  • настройка переноса слов
На это ушло еще несколько дней, скачать и посмотреть что получилось можно со странички репозитория - https://github.com/Beeblerox/BitmapFont
На данный момент там присутствуют три различные версии описываемого компонента:
  • кросс-платформенная версия под Haxe (данная версия используется в порте класса FlxPreloader). Работает на flash, c++ и neko; должно также работать  на iOS и Android, но не проверялось.
  • версия на AS3
  • версия для Flixel, также на AS3. В ней отсутствует возможность задания фона у текста, от этого функционала пришлось отказаться из-за проблем, которые возникнут при портировании на Haxe. Может быть, когда у метода drawTiles() класса TileSheet появиться возможность задавать масштаб тайлов по обеим осям (данный реквест можете помочь продавить в данной теме на форуме haxenme.org), я введу такой функционал, но пока оставлю так.
В каждой из папок есть примеры использования, так что проблем не должно возникнуть.
Версия для Flixel на Haxe находится в работе (на данный момент работает только под flash) и должна быть готова в течение недели (надеюсь, что так и будет :) ).

Напоследок расскажу как создать свой растровый шрифт, для этого вам понадобятся две вещи:
Пример изображения для растрового шрифта
  1.  Графический файл (обычно в формате png), содержащий изображения символов шрифта. Для того, чтобы программа смогла распознать границы изображений символов шрифта, изображение должно иметь фоновую заливку, а изображения символов не должны содержать данного цвета, плюс между символами дожен быть минимум 1 пиксел и каждый ряд изображений символов должен начинаться с одного уровня (см. рисунок выше) 
  2. Строку, содержащую символы, соответствующие изображению. Например, для приведенного выше изображения данная строка будет иметь вид: " !\"#$%&'()*+,-./" + "0123456789:;<=>?" + "@ABCDEFGHIJKLMNO" + "PQRSTUVWXYZ[]^_" + "abcdefghijklmno" + "pqrstuvwxyz{|}~\\"
Чтобы создать сам шрифт нужна всего одна строчка:
_font = new PxBitmapFont(fontBitmapData, fontString);
где fontBitmapData - изображение символов шрифта, а fontString - строка с символами шрифта.
Для создания текстового поля обязательными являются две строки:
_text = new PxTextField(_font); // непосредственно создание текстового поля
_text.setWidth(100); // задание ширины поля, по-умолчанию равна единице


Думаю, что разобраться со свойствами создаваемого таким образом текстового поля не составит особых затруднений (их названия говорят сами за себя и должны быть знакомы, если вы уже работали со стандартными текстовыми полями), поэтому на этом и заканчиваю. А если возникнут какие вопросы - то добро пожаловать в комменты :)

UPD: Стоило мне вчера написать, что не хватает в методе drawTiles() аргументов, задающих масштабные коэффициенты по обеим осям, как уже сегодня в svn-репозитории NME была добавлена эта возможность -- теперь каждому тайлу можно задавать матрицу 2d-преобразований, т.е. не только масштабы и поворот, но и отражение по оси, наклоны и т.д. Вот такие дела. 

понедельник, 16 апреля 2012 г.

Первая игра на FlixelNME

Вот и вышла первая игра на FlixelNME -- Pakkuman's Defense -- это своего рода смесь Pac-man с Tower Defence. Автор игры - Ido Yehieli (Tametick)
Вот вольный перевод отрывка отзыва об игре с сайта http://www.indiegamemag.com:
А вы знали, что первоначально игра Pac-Man должна была называться Puck-Man - производное от японского “паку-паку” - хлопать ртом. А знаете ли вы также, что эта игра станет в сотни раз лучше, если в ней будут элементы товер дефенса? Pakkuman Defense - это одна из таких ретро-игр, в которых намешаны разные элементы. Но кроме обаяния, китча и чувства удовлетворения от уничтожения проклятых привидений в ней есть стратегическая глубина.
Смысл прост: вы играете в Pac-Man, но собираемые точки используются в качестве местной валюты для покупки башен, уничтожающих привидения. И такой простой прием резко меняет всю игру. Так как на поле расположено ограниченное число точек, то вы можете построить строго ограниченное число башен, поэтому важно выбирать наиболее эффективное расположение башен, так как привидения бесконечно респавняться. Случайный дизайн карт более сложный, нежели в оригинале, на них могут быть и тупики и множество мест, где вас могут окружить, поэтому размещение башен вдвойне важно. Другим ключевым моментом является то, что собранные на одном уровне точки переносятся на другой, и если вы потратите все свои деньги на одном уровне, то на следующем вас может ждать катастрофа.
По мнению автора обзора у игры есть два основных недостатка: это отсутствие жизней у главного героя (даже оригинальный Pac-Man не был так жесток в этом отношении) и немного "привередливое" управление, которое иногда не срабатывает. Хотя эти проблемы и вносят свой вклад в общую сложность игры, все-таки они не являются решающими.
Pakkuman Defense - это полностью новое и успешное осмысление идеи Pac-Man.

Игру Pakkuman Defense можно приобрести на сайте http://www.indiebuskers.net/ в составе Buskers Bundle. Данный комплект из 5 инди-игр продается по модели Pay-what-you-want (плати сколько хочешь) и на момент публикации этого поста было продано всего 435 бандлов.

UPD: Оказалось, что Pakkuman Defense - не первая игра на FlixelNME, до нее Ido Yehieli написал игру Fuel, повествующую об астронавте, вынужденном приземлиться на астероиде в поисках топлива для своего корабля:
Эта игра была создана в рамках конкурса 7DRL (Seven Day Roguelike Challenge) и поиграть в нее можно совершенно бесплатно (ссылки для скачивания доступны на странице игры).


понедельник, 19 декабря 2011 г.

Создание порта движка для создания двухмерных игр Flixel на Haxe

1. Что такое Haxe?

Haxe – это объектно-ориентированный язык для кроссплаторменной разработки, в настоящее время в качестве целевых платформ для него выступают flash, javascript, php, c++ (в начале 2012 года ожидаются c# и java). Если Вы раньше писали программы на ActionScript 3, то синтаксис Haxe покажется Вам знакомым (еще один немаловажный плюс). При этом для haxe существует множество различных библиотек, существенно облегчающих различные задачи. Одной из таких библиотек является NME (Neko Media Engine), позволяющая пользоваться flash api при разработке графических приложений для Windows, Mac, Linux, Android, iOS, WebOS, HTML5 и, конечно, flash (куда же без него), это означает, что Вы пишете один код (ну, почти что один), и он работает на всех перечисленных платформах. Кроме того, программы под Windows, Mac, Linux, Android, iOS и WebOS используют аппаратное ускорение графики (через OpenGL, OpenGL ES), что на данный момент дает значительное преимущество в производительности перед флэшом (аппаратное ускорение в котором есть на персоналках, но на мобильных платформах его пока только обещают).

2. Что такое Flixel?

Flixel – это, как ясно из заголовка статьи, движок для 2d-игр, написанный на AS3. Он очень прост для изучения и имеет множество плюшек (далее вольный перевод с официального сайта):
- отображение на экране тысяч объектов;
- объединение объектов в группы (например, для обработки столкновений между группами);
- встроенная простая система столкновений между объектами;
- системы частиц;
- создание уровней с помощью tilemap’ов (для этого существует ряд редакторов, лучшим считается dame-editor);
- дополнительные классы для отображения текста, работы с сохранением игр, скроллинга игрового мира;
- классы для работы с клавиатурой и мышью;
- утилиты для работы с цветом и геометрическими преобразованиями.
В число «продвинутых» особенностей движка входят:
- возможность записи и воспроизведения игрового процесса;
- встроенный визуальный отладчик;
- система камер, позволяющая создавать игры в режиме split-screen (и не только);
- функция поиска пути в плиточном мире;
- простая система многократного использования объектов (object recycling).

3. Flixel + Haxe = HaxeFlixel

В качестве эксперимента (и более глубокого понимания языка, а также основ геймдева) решил я портировать Flixel на Haxe. Было это в середине лета (2011). К тому времени уже существовал ряд таких портов, единственным их минусом было «моральное устаревание» (просто это порты более старых версий). В качестве основы был взят этот порт, т.к. он считался наиболее завершенным и у него было наибольшее число «наблюдателей». Спасибо автору, т.к. без его работы моего порта могло бы и не быть. И так, в середине июля, пошел процесс: в одной вкладке FlashDevelop’а я открывал файл на as3 и переводил его на haxe, а во второй – его старый порт, с которым сверялся в трудных для понимания местах (т.к. язык знал плохо). Примерно за 2 недели все классы были переведены, потом я на две недели уехал в «отпуск». А после возвращения начались попытки компиляции простеньких примеров – сразу же посыпался «мильон» ошибок, большая часть из которых решалась крайне просто – путем приведения типов переменных к нужному виду. Дело в том, что в Haxe более строгая типизация, чем в AS3, поэтому, если некоторый метод ожидает в качестве аргумента получить целочисленное значение (Int), а Вы передается ему число с плавающей точкой (Float – местный аналог Number), то это вызовет ошибку компиляции. AS3 в этом отношении менее строг и сам отбросит дробную часть. На данном этапе больше всего мне запомнился момент, когда после очередной попытки запуска проекта вылетело где-то 250 ошибок, а после исправления пары из них их стало за 300 (рифмовать не надо :)). К середине сентября простые примеры уже начали запускаться и начался отлов ошибок портирования, чистка кода.
Началом следующего этапа в создании порта стала новость о выходе новой версии библиотеки NME 3.0 (начало октября), которая обещала более простой процесс кроссплаторменной разработки и множество улучшений в работе. Почитав на официальном форуме в списке рассылки о преимуществах новой версии этой библиотеки, решил интегрировать их, чтобы была возможность писать игрушки под мобилы (так, ради интереса, смартфона-то у меня и нет). Это было несложно: те места, которые не хотели компилироваться на c++, я просто комментировал так, чтобы они исполнялись только на flash-платформе. Тогда из порта пришлось выбросить сохранения игр. Где-то за неделю я управился и оставил на форуме haxenme.org сообщение о своем порте. Ответы не порадовали: для меня оказалось новостью, что операции с битмапами (а они являются основой системы рендеринга flixel) выполняются на cpu (а он, на телефонах слабоват) и простые демки дико тормозили (ну вот такой я нуб-самоучка). Кроме опроса на форуме, проводились тесты и на компьютере, они тоже дали неутешительный результат – программы, скомпилированные под с++, работали даже медленнее, чем во flash-player’e. После этого начались поиски наиболее оптимальных методик для работы с графикой. Слава Богу, что эту работу до меня уже сделали члены haxe-сообщества: для быстрой обработки графики предлагалось использовать операции drawTriangles и drawTiles. С первой Вы, скорее всего, знакомы, т.к. она присутствует во флэше (для тех, кто не знает: с помощью этой команды можно нарисовать треугольник, используя в качестве «текстуры» любую битмапдату). Вторая операция – нововведение в NME, она аналогична drawTriangles, но отрисовывает уже прямоугольник (пока что работает только в c++). Первоначальная реализация данного метода была довольно негибкой: можно было задавать только положение такого прямоугольника, поэтому я решил использовать drawTriangles и посвятил пару недель экспериментированию. Но результаты меня не устраивали, ведь drawTriangles не позволяет задавать цветовую трансформацию отрисовываемой текстуры, а я очень этого хотел (иначе пришлось бы сделать еще одно «обрезание» моему порту). И тут вышел первый релиз-кандидат NME 3.1, в котором появилась возможность кроссплатформенной работы с LocalSharedObject (т.е. вернулась возможность сохранять игры на всех поддерживаемых платформах), улучшенная работа с ассетами (шрифтами, графическими, звуковыми и текстовыми файлами), а также (барабанная дробь) расширение функционала метода drawTiles – теперь он позволяет задавать тайлам масштаб, поворот, прозрачность и цветовую трансформацию. Радости моей не было предела, начался новый этап экспериментирования с этим методом. С нюансами его работы разобраться удалось не сразу. Оказалось, что работать с ним нужно аккуратно, т.к. если пытаться использовать одну и ту же битмапдату в качестве «текстуры» для двух разных tileSheet’ов (объектов для отрисовки тайлов), то «волшебным» образом пропадали прозрачность и цветовые трансформации. Но оно и к лучшему, т.к. это заставило более внимательно относиться к ресурсам, не создавая «дублирующих» объектов. Таким образом, я пришел к идее класса-менеджера, отвечающего за работу всех tileSheet’ов – он является центром всей новой системы рендеринга. Если в оригинальном Flixel’е каждый объект непосредственно рисуется на битмапдате камеры, то в новой системе каждый объект передает в менеджер свои данные (положение, поворот, масштаб и т.д.), и только после того, как все объекты передадут свои данные, идет отрисовка всех тайлов. С этой особенностью связана еще одна проблема – проблема сортировки глубины отрисовки объектов. Если в оригинальном Flixel’е порядок отрисовки можно изменить отсортировав массив самих объектов (отрисовка ведется в порядке их расположения в таком массиве), то в новой системе объекты отрисовываются пакетно, т.е. все объекты, имеющие в качестве графического представления одну и ту же битмапдату, отрисовываются за одну операцию. Эту проблему удалось решить частично за счет:
- возможности отдельной сортировки объектов, делящих между собой одну и ту же битмапдату (т.е. уже имеющимися средствами flixel);
- а также возможности сортировки самих tileSheet’ов в менеджере (для этого были добавлены соответствующие методы для получения текущей глубины отрисовки tileSheet’а и ее изменения).
Разработав основу новой системы, я провел несколько тестов и увидел значительный прирост в производительности, т.к. теперь операции отрисовки в с++ программах стали осуществляться с помощью gpu. Убедившись, что теперь можно показать предварительный результат работы, я снова написал на форум; отзывы показали, что работа не была потрачена впустую (это было в начале декабря). Эти отзывы придали мне новых сил, и я с удвоенным рвением продолжил доработку системы рендеринга, попутно заборов еще парочку багов.
Теперь немного о грустном. К сожалению, в NME еще не все так гладко (хотя в последнее время библиотека очень сильно преобразилась в лучшую сторону), например, есть некоторые проблемы с клавиатурой, когда нажатия на разные клавиши выдают одинаковые значения кодов (keyCode), поэтому пока что неправильно работают клавиши цифрового блока, а также F1-F12. Также для звука на с++ приходиться конвертировать файлы в wav-формат (а это дополнительный объем), если же использовать mp3, то одновременно получается воспроизводить только один звук. Кроме того, под c++ реализован еще не весь flash api, и мне пришлось писать свою упрощенную реализацию метода hitTest для битмапдаты. Некоторые методы класса BitmapData работают не так, как на флэше, из-за чего возникают артефакты – здесь тоже пришлось писать свою реализацию (для зеркального отражения битмапдаты).
Но, как я уже сказал раньше, библиотека постоянно улучшается, и я надеюсь, что эти проблемы скоро уйдут в небытие.
Ах да, чуть не забыл дать ссылку на репозиторий проекта: https://github.com/Beeblerox/HaxeFlixel
А также скомпилированная на c++ демка (под Windows): https://github.com/downloads/Beeblerox/HaxeFlixel/ModeDemo20122011.zip