Если вы работаете с HaxeNME то возможно вы замечали, что время от времени собранные приложения работают на JS/HTML5 не так как на остальных платформах. Или не работают вовсе. Или даже не собираются из-за какого-то недостающего кода.
Причины, в принципе, понятны - само по себе воссоздание Flash API на JavaScript+HTML5 не выглядит слишком легкой задачей, так как многие из функций существуют немного в другом виде или изначально не существуют вовсе, требуя некоторых ухищрений для реализации.
А состоящая из ухищрений кодовая база, конечно, не будет такой уж и стабильной, особенно при воссоздании функционала на основе "тестирования черного ящика".
К примеру, если вы решили на каждом кадре очищать какой-то буфер размером 640х480 пикселей с помощью BitmapData.fillRect, вы совершаете большую ошибку, так как данная функция делает это не просто попиксельно, а еще и с использованием ImageData.
В общем, данная статья посвящена замене в NME проекте browser/jeash библиотеки на свою при компиляции в JS.
Подготовка
Как ни странно, возможность замены библиотеки при экспорте в JS предусмотрена и существует уже некоторое время.
Первое что нужно сделать - собственно исключить библиотеку для JS/HTML5. Это делается довольно очевидным способом, заменой одной строки в application.nmml с
<haxelib name="nme" />
на<haxelib name="nme" unless="html5" />
Но, все не настолько просто. NME-build устроен таким (странным) образом, что если в коде где-то есть отсылка к какому-либо классу NME, то в проект будет включен NME Preloader, что включает за собой Bitmap, Sprite, и BitmapData, что влекут за собой еще классы... и все это обрывается ошибками, потому что непосредственного NME нет (он же выключен директивой выше). Поэтому, для проверки, главный класс можно сократить до чего-то в этом роде:
package ; class Main { public function new() { trace("Oh, hi."); } static function main() { new Main(); } }
Это успешно соберется и запустится на разных платформах как и ранее. Но с одним различием - теперь в .JS файле нет никакого NME. Да и вообще почти ничего нет, кроме величественно минималистичного класса Main и нескольких методов из Reflect/Boot.
Реализация
Конечно, код отлично работает когда его нет (требуется цитата) но приложение как-то работать должно, и в частности должен работать NME код при сборке не под JS, в то время как JS код не должен лезть в остальные платформы.
К счастью, в Haxe для этого есть препроцессоры, и код ограничивается структурой этого рода:
#if js // JS(+HTML5) реализация #else // NME реализация #end
Для "единства" интерфейса используемых в приложении классов подобным образом должны быть указаны typedef'ы или реализации классов, чтобы подставленный компилятором класс содержал используемые методы и свойства на всех платформах (стоит заметить что подобный подход так же используется в классах самого NME). К примеру, для реализации буфера/текстуры для JS должен будет быть сделан класс, обертывающий HTML5'Canvas, в то время как для NME может быть использован BitmapData или BitmapData+Sprite/Shape, зависимо от нужд.
Данный подход позволяет лучше оптимизировать выводимый код, что может быть особенно заметно для мобильных приложений (где лишняя прорисовка в буфер Jeash уже стоит и так дорогого времени).
Основными недостатками является нужда непосредственной реализации нужных классов (занимает время), а так же нужда реализации загрузчика ресурсов и данных приложения (посредством макросов).
Приложенный пример демонстрирует реализацию вышеописанного способа для относительно простого класса поддержки рисования через Canvas и BitmapData (буфер), на выходе идентично работающего для JS и NME.
Скачать ZIP
(проект для FlashDevelop)