Создание многокадровой флешки с помощью mxmlc
Запись от ps_spectre размещена 03.02.2011 в 16:41
Обновил(-а) ps_spectre 03.02.2011 в 17:34 (добавил немного объяснений)
Обновил(-а) ps_spectre 03.02.2011 в 17:34 (добавил немного объяснений)
Итак, предположим нам потребовалось скомпилировать наш проект и получить на выходе swf файл в котором будет больше одного кадра.
Зачем нам это может понадобиться?
Классический вариант — разработка приложения (например игры) с прелоадером.
Что такое прелоадер? Это графическое представление процесса загрузки swf файла флеш плеером. В случае с однокадровой флешкой, мы не имеем возможности что-либо отобразить, т.к. флеш плеер еще не начал отображение нашего swf файла и при этом, самостоятельно он ничего не выводит на экран (как сильверлайт или JavaFX). Если у нас флешка мегабайт на 10, и все в одном, первом, кадре, то пользователь будет даже не догадываться, что флеш плеер ведет загрузку swf.
Для этого нам и надо его (пользователя) уведомить в том, что процесс загрузки идет и убегать никуда не надо со странички,)
В случае с многокадровыми флешками, флеш плеер работает следующим образом: когда видит, что первый кадр полностью готов, начинает процесс отображение на экран, даже если остальные кадры еще не готовы.
(если грузим из кода Loader'ом многокадровый swf, то в коде init событие наступает когда первый кадр готов, complete когда все загрузились)
Отсюда возникает хорошее следствие, мы можем полностью использовать все классы/ресурсы которые уже загрузились.
Чтобы сделать просто прелоадер, достаточно написать класс, который будет грузиться самым первым (в первом кадре), и в нем, по какому-нибудь событию (например по таймеру или лучше ProgressEvent.PROGRESS у loaderInfo) проверять кол-во загрузившихся кадров (или байт) и выводить информацию пользователю.
Первое, что надо учесть в случае с многокадровой флешкой, так это то, что наш основной класс должен наследоваться от MovieClip , а не Sprite.
Основной класс, этот тот, который указывается компилятору (mxml Main.as) (root класс, который на stage добавится) (в терминах FlashIDE — это по-моему основной timeline)
Если мы хотим сделать флешку с прелоадером, то основным классом будет Preloader.as который наследуется от MovieClip.
Рассмотрим простой пример, у нас есть Preloader.as
package { import flash.display.*; import flash.events.*; import flash.text.TextField; import flash.utils.getDefinitionByName; [SWF(width=800,height=600,frameRate=30,backgroundColor=0xC254DE)] public class Preloader extends MovieClip { private var _txt:TextField = new TextField(); public function Preloader() { if (stage) { stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; addChild(_txt); } addEventListener(Event.ENTER_FRAME, checkFrame); loaderInfo.addEventListener(ProgressEvent.PROGRESS, progress); } private function progress(e:ProgressEvent):void { _txt.text = loaderInfo.bytesLoaded.toString(); } private function checkFrame(e:Event):void { if (loaderInfo.bytesLoaded == loaderInfo.bytesTotal && currentFrame == totalFrames) { stop(); loadingFinished(); } } private function loadingFinished():void { removeEventListener(Event.ENTER_FRAME, checkFrame); loaderInfo.removeEventListener(ProgressEvent.PROGRESS, progress); startup(); } private function startup():void { var mainClass:Class = getDefinitionByName("Game") as Class; stage.addChild(new mainClass() as DisplayObject); } } }
Так же есть у нас класс, например Game.as, который уже интенсивно использует ресурсы и все такое.
А так же две библиотеки balloons.swc, assetLibrary.swc
Рассмотрим класс Game.as
package { import flash.display.DisplayObject; import flash.display.Sprite; import flash.events.Event; import assets.graphics.textures.Grass_textureJpg; public class Game extends Sprite { public function Game():void { init(); } private function init(e:Event = null):void { addChild(new BackImage()); addChild(new PlayerImage()); addChild(new Grass_textureJpg()); } } }
Компилятор позволяет включать библиотеки двумя основными способами в конечный файл.
1. Полностью включит все что найдет в библиотеке.
2. Включить только те классы, на которые найдены ссылки.
Во FlashDevelop это в опциях включения SWC называется:
1. Included Library (include completely)
2. Library (Include referenced classes)
Это соответствует ключам компилятора:
1. -include-libraries <name.swc>
2. -compiler.library-path (alias -l)
На самом деле компилятор еще позволяет очень полезную фишку, библиотеку пометить как внешнюю (external library)
Но в этом случае нам придется файл swf (который нужно вынуть из swc) грузит ручками в рантайме. Указание внешней swc дает фишку в том, что во время компиляции у нас будет проверка наличия класса (Compile-time type-checking). (не надо использовать getDefinition())
ключ компилятору:
compiler.external-library-path (alias -external-library-path)
во флеш девелоп External-library (not included)
И так, возвращаемся к нашему примеру.
Для простоты учитываем, что все находится в одном каталоге (Preloader.as, Game.as, balloons.swc, assetLibrary.swc)
Самый главный вопрос, КАК сделать МНОГОКАДРОВЫЙ (в 99.9% хватает двух кадров) SWF файл?
ответ очень простой, у компилятора mxmlc существует ключ -frame <label> <class>
(-----
Q: почему я не могу в хелпе увидеть набирая mxmlc -help list?
A: используйте mxmlc -help advanced list
------)
Рассмотрим на нашем примере
Код:
mxmlc Preloader.as -frame 1 Game -include-libraries=balloons.swc,assetLibrary.swc -debug -output game.swf
В итоге получается 2х кадровая флешка, которая называется game.swf, с первым кадром около 1килобайта, а на 2 втором кадре уже размер того, чего мы включили. (если библы весят 10 метров, значит во втором кадре будет минимум 10 метров)
Дополнение:
при этом, никаких классов из Flex фреймворка не подтягивается.
Если нам не надо полностью включать наши библиотеки в конечный результат, а только те классы, на которые есть ссылки, то
Код:
mxmlc Preloader.as -frame 1 Game -l . -debug -output game.swf
-l . указывается компилятору искать в текущем каталоге .swc файлы и оттуда во время компиляции включать классы на которые есть ссылки
(FlashDevelop: Library (Include referenced-classes))
Вот и все! Таким простым способом мы делаем многокадровую флешку.
Если нам надо не 2 кадра, а больше
просто перечисляем
Код:
mxmlc Preloader.as -frame 1 SomeClass1 -frame 2 SomeClass2 -frame3 SomeClass3 ...
Дополнение:
внимание, если использовать в классе preloader.as ссылки на что-либо из библиотеки, то это что-либо будет подтягиваться в первый кадр. (где прелоадер)
подтягивается в тот кадр, на котором есть ссылки.
например
mxmlc Preloader.as -frame 1 SomeClass1 -frame 2 SomeClass2 -frame3 SomeClass3
если в классе SomeClass1 ссылки на 5 классов с картинками, они подгрузятся на второй кадр.
если в классе SomeClass2 ссылки на другие классы с картинками, то они будут подгружатся в 3й кадр.
и т.д.
поэтому в прелоадере избегать ссылок на классы, которые много весят. (чтобы первый кадр был как можно меньше)
так же все команды можно писать в config.xml , и во время компиляции указывать подгружать конфиг
-load-config+=config.xml
customConfig.xml
Код:
<?xml version="1.0"?> <flex-config> <compiler> <include-libraries> <library>balloons.swc</library> <library>assetLibrary.swc</library> </include-libraries> </compiler> <frames> <frame> <label>1</label> <classname>Game</classname> </frame> </frames> </flex-config>
Код:
mxmlc Preloader.as -load-config+=customConfig.xml -output game.swf
в классе Game.as и компилировать как основной класс
[Frame(factoryClass="Preloader")]
Для меня минус один, для чистого AS3 проекта, при таком способе, компилятор тянет много флекс мусора. (mx.*)
В случае флекс проекта, это уже называется не мусор, а много нужных классов из фреймворка флекс.
В случае флекс проекта, у нас как не крути, будут очень много mx.* классов, и этот метатег подойдет нативно.
Для меня еще минус чисто восприятия, мета-тег с такой эдакой фабрикой, не так четко воспринимается как нативный ключ -frame.
Спасибо за внимание, надеюсь я не сильно в роли Капитана Очевидности выступил, и кому-то это поможет начать делать проекты с нормальным прелоадером.
Всего комментариев 13
Комментарии
03.02.2011 18:42 | |
Спасибо, наконец-то я понял, как с помощью External-library подгружать графический контент.
|
04.02.2011 00:38 | |
Большое спасибо, всегда использовал [Frame(factoryClass="Preloader")], думал это единственный способ.
|
04.02.2011 13:46 | |
Аналогично с Hyzhak, спасибо!
Можно поподробнее про external library? |
04.02.2011 15:25 | |
Psycho Tiger, хорошо, постараюсь написать чуть более подробно про линкование внешней библиотеки.
|
08.02.2011 09:59 | |
Во Flex есть еще по крайней мере два способа создания двухкадрового DocumentClass. Один из них подойдет и для FD, т.к. он использует flex config.
|
08.02.2011 14:15 | |
dimarik, один из них метатегом Frame Factory, а второй?
|
08.02.2011 21:35 | |
Тигра, flex config, очевидно.
|
08.02.2011 22:14 | |
М... ты просто сказал "ещё два способа". flex-config, по сути, рассмотрен в статье.
|
09.02.2011 01:34 | |
Хм. Каюсь, проглядел. Принято в начале описывать известные способы, а уже потом акцентировать внимание на собственных изысканиях. Вероятно, автор статьи никогда не писал курсовики, дипломные работы и докторские диссертации.
|
|
Обновил(-а) dimarik 09.02.2011 в 01:42
|
Последние записи от ps_spectre
- Используем фичи flash player 10.2 или 11.0 во FlashIDE CS5 (08.03.2011)
- mxmlc: подключение внешней библиотеки (external library) (04.02.2011)
- Создание многокадровой флешки с помощью mxmlc (03.02.2011)
- Создание библиотеки ресурсов (swc) с помощью compc (02.02.2011)