Недавно мне нужно было сделать небольшой SWF-ролик с парой кнопок и несколькими картинками. Так как мой основной рабочий инструмент - Linux, то и делать ролик решил с помощью " открытого" программного обеспечения. Кстати, это же программное обеспечение доступно и под Windows.
Компания Adobe в данный момент предоставляет Flex4 SDK - бесплатное программное обеспечение для компиляции SWF-файлов из исходников, написанных на ActionScript 3. 0 (далее - AS3). Flex4 SDK содержит все библиотеки Flex, библиотеки Flash MX, и компилятор mxmlc, с помощью которого можно компилировать в формат SWF как файлы *. mxml (формат Flex), так и AS3-программы.
Сразу скажу пользователям Windows - Flex4 SDK есть и под Windows, однако лучше сразу установить и среду FlashDevelop. Это удобная OpenSource среда разработки, которая после правильной настройки включает в себя все нужные части из Flex SDK. Она предназначена для комфортного написания и компилирования AS3-кода. Так как FlashDevelop завязан на Win API и библиотеку. NET, его портирование под Linux затруднено, поэтому в Linux приходится довольствоваться только Flex4 SDK. В любом случае, приведенный в статье код скомпилируется не только в " чистом" Flex4 SDK, но и в настроенном FlashDevelop.
В этой статье я приведу код небольшого приложения, которое компилируется с помощью компилятора mxmlc в SWF файл. Называться программа будет " Просмотрщик картинок". Окно программы будет содержать следующие элементы:
В коде будет показано, как реализуются следующие вещи:
· Как импортировать картинки вовнутрь SWF
· Как сделать простую кнопку
· Как сделать функцию-обработчик клика по кнопке
· Как сделать кнопку, при клике на которую следует переход на заданный URL
· Как показать и двигать картинку на экране
· Как сделать основной цикл программы (mainloop)
· Как сделать прелоадер (preloader)
Полученных знаний будет достаточно, чтобы написать небольшуюFlash-игруначистом Action Script v. 3. 0. Итак, начнём.
* * *
Приложение будет состоять из трех файлов:
· Main. as - основной файл программы
· PushButton. as - класс, реализующий кнопку
· Preloader. as - класс, реализующий прелоадер
Назначение файлов Main. as и Preloader. as, в принципе, понятно. А зачем нужен PushButton. as? Неужели во Flash нет готовой реализации обычной кнопки? Да, нет. На дворе 2010 год, а во Flash добавить обычную кнопку одной командой невозможно. Точнее, классическая кнопка есть, но находится она в библиотеке Flex. А использовать одновременно объекты Flex и более привычные объекты Flash нельзя. Мы будем реализовывать программу с помощью объектов Flash (ибо Flex - это отдельная большая песня), так что кнопку нам придется сделать самостоятельно.
Файл Main. as:
package { import flash. display. Sprite; import flash. text. TextField; import flash. display. DisplayObject; import flash. display. SimpleButton; import flash. events. MouseEvent; import flash. events. Event; import flash. net. URLRequest; import flash. net. navigateToURL; import flash. utils. getDefinitionByName; import PushButton; // Класскнопки, лежащийв PushButton. as
// Параметры SWF-файла [SWF(height=" 380" )] // Интегрированиепрелоадера, лежащегов Preloader. as [Frame(factoryClass=" Preloader" )]
// Основнойкласспрограммы public class Main extends Sprite {
// Картинкикадров (будутхранитьсявмассивекакDisplayObject) public varkadr: Array=new Array(); // Параметрыкартинок-кадров public varkadr_num: int=3; // Количествокартинок-кадров public varkadr_current_num: int=1; public varkadr_move_step: int=10; public varkadr_size_x: int=464; public varkadr_size_y: int=380; // Текущеесостояниепрограммы public varstate: String=" wait_action"; // Конструкторосновногокласса public function Main(): void { if (stage) init(); else addEventListener(Event. ADDED_TO_STAGE, init); } // Точкавхода, послетогокакзагрузилсявесьролик public function init(e: Event = null): void { var i: int; // Отключениеобслуживанияпрелоадера removeEventListener(Event. ADDED_TO_STAGE, init); // Библиотекакартинок [Embed(source=" logo.png" )] varsymbol_logo: Class; [Embed(source=" kadr_1.png" )] var symbol_kadr_1: Class; [Embed(source=" kadr_2.png" )] var symbol_kadr_2: Class; [Embed(source=" kadr_3.png" )] var symbol_kadr_3: Class; // Загрузка (созданиеинстанта) картинкилоготипаизбиблиотеки varlogo: DisplayObject=new symbol_logo(); // Загрузка (созданиеинстанта) картинокскадрамиизбиблиотеки kadr[1]=new symbol_kadr_1(); kadr[2]=new symbol_kadr_2(); kadr[3]=new symbol_kadr_3(); // Длязагрузки (созданиеинстанта) можнопопробоватьдругойкод: /* for(i=1; i< =kadr_num; i++) { varimg: Class=getDefinitionByName(" symbol_kadr_" + i. toString()) as Class; kadr[i]=new img(); } */ // Логотипдобавляетсявсписокотображения Sprite, // откоторогонаследованкласс Main // Другимисловами, логотиппростодобавляетсянахолст addChild(logo); logo. x=kadr_size_x+27; // Задаютсякоординаты logo. y=25; // Картинкикадровдобавляютсянахолстскоординатами 0: 0 // иделаютсяневидимыми for(i=1; i< =kadr_num; i++) { addChild(kadr[i]); kadr[i]. visible=false; } // Перваякартинка-кадрделаетсявидимой kadr[kadr_current_num]. visible=true; // Надписьналоготипедобавляетсянахолст vardisplay_txt: TextField = new TextField(); display_txt. text = " ImageView"; display_txt. selectable=false; display_txt. x=kadr_size_x+15; display_txt. y=5; addChild(display_txt); // Добавляемкнопку " Назад", указываемееобработчик varback_button: PushButton=new PushButton(kadr_size_x+30, 150, 24, 24, " ᐃ " ); back_button. addEventListener(MouseEvent. CLICK, back_click); addChild(back_button); // Добавляемкнопку " Вперед", указываемееобработчик varforward_button: PushButton=new PushButton(kadr_size_x+30, 180, 24, 24, " ᐁ " ); forward_button. addEventListener(MouseEvent. CLICK, forward_click); addChild(forward_button); // Добавляемкнопку " Site", указываемееобработчик vargo_button: PushButton=new PushButton(kadr_size_x+23, kadr_size_y-18, 42, 16, " Site" ); go_button. addEventListener(MouseEvent. CLICK, go_click); addChild(go_button); // Запускаемосновнойцикл (main loop) addEventListener(Event. ENTER_FRAME, main_loop); } // Основнойцикл public function main_loop(event: Event): void { if(state==" wait_action" ) return; // Еслипроисходитдвижениевперед (кадрыдвижгаютсявверх) if(state==" roll_forward" ) { // Y-координатакадровуменьшаетсянанужныйшаг kadr[kadr_current_num]. y-=kadr_move_step; kadr[kadr_current_num+1]. y-=kadr_move_step; // Когдакадрполностьюперемотан if(kadr[kadr_current_num]. y< =(-kadr_size_y)) { // Уехавшийкадрскрывается kadr[kadr_current_num]. y=0; kadr[kadr_current_num]. visible=false; // Приехавшийкадрвыравнивается kadr[kadr_current_num+1]. y=0; kadr_current_num=kadr_current_num+1; state=" wait_action"; } } // Еслипроисходитдвижениеназад (кадрыдвигаютсявниз) if(state==" roll_back" ) { // Y-координатакадровувеличиваетсянанужныйшаг kadr[kadr_current_num]. y+=kadr_move_step; kadr[kadr_current_num-1]. y+=kadr_move_step; // Когдакадрполностьюперемотан if(kadr[kadr_current_num]. y> =kadr_size_y) { // Уехавшийкадрскрывается kadr[kadr_current_num]. y=0; kadr[kadr_current_num]. visible=false; // Приехавшийкадрвыравнивается kadr[kadr_current_num-1]. y=0; kadr_current_num=kadr_current_num-1; state=" wait_action"; } } } // Обработкакнопкиназад (т. е. вверх) private function back_click(event: MouseEvent): void { if(state==" wait_action" ) { // Перемещатьсянельзя, еслиначальныйкадр if(kadr_current_num==1) return; state=" roll_back"; kadr[kadr_current_num]. visible=true; kadr[kadr_current_num-1]. x=0; kadr[kadr_current_num-1]. y=(-kadr_size_y); kadr[kadr_current_num-1]. visible=true; } } // Обработкакнопкивперед (т. е. вниз) private function forward_click(event: MouseEvent): void { if(state==" wait_action" ) { // Перемещатьсянельзя, есликонечныйкадр if(kadr_current_num==(kadr_num)) return; state=" roll_forward"; kadr[kadr_current_num]. visible=true; kadr[kadr_current_num+1]. x=0; kadr[kadr_current_num+1]. y=kadr_size_y; kadr[kadr_current_num+1]. visible=true; } } // Обработкакнопкипереходапоуказанному URL private function go_click(event: MouseEvent): void { var url: String=" https: //webhamster. ru"; varurl_request: URLRequest=new URLRequest(url); navigateToURL(url_request, " _self" ); } } }
Файл Preloader. as:
package { import flash. display. DisplayObject; import flash. display. MovieClip; import flash. display. StageAlign; import flash. display. StageScaleMode; import flash. events. Event; import flash. events. IOErrorEvent; import flash. events. ProgressEvent; import flash. utils. getDefinitionByName; import flash. text. TextField; import flash. text. TextFieldAutoSize; import flash. display. LoaderInfo; public class Preloader extends MovieClip { private varpreloader_text: TextField; // Геометрия SWF файла private varswf_w: int=550; private varswf_h: int=380;
// Инициализациязагрузчика public function Preloader() { if (stage) { stage. scaleMode = StageScaleMode. NO_SCALE; stage. align = StageAlign. TOP_LEFT; } addEventListener(Event. ENTER_FRAME, checkFrame); loaderInfo. addEventListener(ProgressEvent. PROGRESS, progress); loaderInfo. addEventListener(IOErrorEvent. IO_ERROR, ioError); // Текстосостояниизагрузкивыводитсянаэкран preloader_text=new TextField(); preloader_text. text=" Load 0 % "; preloader_text. textColor=0xA0A0A0; preloader_text. selectable=false; preloader_text. autoSize=TextFieldAutoSize. CENTER; preloader_text. x=swf_w/2-preloader_text. width/2; preloader_text. y=swf_h/2; addChild(preloader_text); } private function ioError(e: IOErrorEvent): void { trace(e. text); }
// Метод, вызываемыйприизмененииколичествазагруженныхбайт private function progress(e: ProgressEvent): void { // Обновляетсятекстзагрузчика preloader_text. text=" Load " +(Math. round((loaderInfo. bytesLoaded*100)/loaderInfo. bytesTotal))+" %"; } private function checkFrame(e: Event): void { if (currentFrame == totalFrames) { stop(); loadingFinished(); } }
// Завершениезагрузки private function loadingFinished(): void { removeEventListener(Event. ENTER_FRAME, checkFrame); loaderInfo. removeEventListener(ProgressEvent. PROGRESS, progress); loaderInfo. removeEventListener(IOErrorEvent. IO_ERROR, ioError); // Текстзагрузчикаскрывается preloader_text. visible=false; startup(); } private function startup(): void { varmainClass: Class = getDefinitionByName(" Main" ) as Class; if (parent == stage) stage. addChildAt(new mainClass() as DisplayObject, 0); else addChildAt(new mainClass() as DisplayObject, 0); } } }
Файл PushButton. as
package { import flash. display. Sprite; import flash. display. DisplayObject; import flash. display. SimpleButton; import flash. text. TextField; import flash. text. TextFieldAutoSize; public class PushButton extends SimpleButton { private varbutton_x: Number=0; private varbutton_y: Number=0; private varbutton_width: Number=0; private varbutton_height: Number=0; private varbutton_text: String=" "; public function PushButton(buttonX: Number, buttonY: Number, buttonWidth: Number, buttonHeight: Number, buttonText: String) { button_x=buttonX; button_y=buttonY; button_width=buttonWidth; button_height=buttonHeight; button_text=buttonText; upState=button_sprite(0x888888); overState=button_sprite(0x999999); downState=button_sprite(0xAAAAAA); hitTestState=button_sprite(0xBBBBBB); x=buttonX; y=buttonY; } private function button_sprite(color: uint = 0x888888): Sprite { varb_sprite: Sprite=new Sprite(); b_sprite. graphics. lineStyle(1); b_sprite. graphics. beginFill(color); b_sprite. graphics. drawRect(0, 0, button_width, button_height); b_sprite. graphics. endFill(); varbutton_label: TextField; button_label=new TextField(); button_label. text=button_text; button_label. selectable = false; button_label. autoSize=TextFieldAutoSize. CENTER; button_label. x=(button_width-button_label. textWidth)/2-1; button_label. y=(button_height-button_label. textHeight)/2-2; b_sprite. addChild(button_label); return b_sprite; } } }
Пара пояснений. Весь ролик существует в одном кадре. Основной цикл (mainloop) организован с помощью обработки события перехода на начало кадра. Так как ролик состоит из одного кадра, то mainloop вызывается с частотой смены SWF-кадров, обычно это 12 раз в секунду.
Основной класс программы (класс Main) унаследован от объекта Sprite. Поэтому основной объект можно рассматривать как холст, на котором происходят всякие преобразования. На него можно ложить элементы с помощью метода addChild(). Эти элементы можно скрывать и показывать, можно перемещать, меняя их координаты.
Запустить компиляцию можно с помощью следующей команды:
mxmlc -debug Main. as
Опция -debug нужна, чтобы нормально работала функция trace(). Путь к компилятору mxmlc нужно добавить в переменную PATH, либо указывать полный путь к бинарнику компилятора. В данный момент, в Flex4 SDK компилятор располагается в подкаталоге /bin каталога, куда был установлен Flex4 SDK.
Вот что в результате должно получиться:
|