Собираем
информацию
по крупицам
Статьи - Компьютерное

Web - разработка

Пример простого Flash приложения на Action Script 3, компилируемого с помощью MXMLC
09-10-2010
14:35:51

Недавно мне нужно было сделать небольшой SWF-ролик с парой кнопок и несколькими картинками. Так как мой основной рабочий инструмент - Linux, то и делать ролик решил с помощью "открытого" программного обеспечения. Кстати, это же программное обеспечение доступно и под Windows.

 

Компания Adobe в данный момент предоставляет Flex4 SDK - бесплатное программное обеспечение для компиляции SWF-файлов из исходников, написанных на Action Script 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
  • Как показать и двигать картинку на экране
  • Как сделать основной цикл программы (main loop)
  • Как сделать прелоадер (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(width="550", height="380")]

// Интегрирование прелоадера, лежащего в Preloader.as
[Frame(factoryClass="Preloader")]

 

// Основной класс программы
public class Main extends Sprite
{

 // Картинки кадров (будут храниться в массиве как DisplayObject)
 public var kadr:Array=new Array(); 

 // Параметры картинок-кадров
 public var kadr_num:int=3; // Количество картинок-кадров
 public var kadr_current_num:int=1;
 public var kadr_move_step:int=10;
 public var kadr_size_x:int=464;
 public var kadr_size_y:int=380;

 // Текущее состояние программы
 public var state: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")] var symbol_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;

   // Загрузка (создание инстанта) картинки логотипа из библиотеки
  var logo: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++)
  {
   var img: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;


  // Надпись на логотипе добавляется на холст
  var display_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);


   // Добавляем кнопку "Назад", указываем ее обработчик
  var back_button:PushButton=new PushButton(kadr_size_x+30,150,24,24,"ᐃ");
  back_button.addEventListener(MouseEvent.CLICK, back_click);
  addChild(back_button);

  // Добавляем кнопку "Вперед", указываем ее обработчик
  var forward_button:PushButton=new PushButton(kadr_size_x+30,180,24,24,"ᐁ");
  forward_button.addEventListener(MouseEvent.CLICK, forward_click);
  addChild(forward_button);

  // Добавляем кнопку "Site", указываем ее обработчик
  var go_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";
  var url_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 var preloader_text:TextField;

  // Геометрия SWF файла
  private var swf_w:int=550;
  private var swf_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
  {
   var mainClass: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 var button_x:Number=0;
 private var button_y:Number=0;
 private var button_width:Number=0;
 private var button_height:Number=0;
 private var button_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
 {

  var b_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();

  var button_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;
 }
 
}

}

 

Пара пояснений. Весь ролик существует в одном кадре. Основной цикл (main loop) организован с помощью обработки события перехода на начало кадра. Так как ролик состоит из одного кадра, то main loop вызывается с частотой смены SWF-кадров, обычно это 12 раз в секунду.

 

Основной класс программы (класс Main) унаследован от объекта Sprite. Поэтому основной объект можно рассматривать как холст, на котором происходят всякие преобразования. На него можно ложить элементы с помощью метода addChild(). Эти элементы можно скрывать и показывать, можно перемещать, меняя их координаты.

 

Запустить компиляцию можно с помощью следующей команды:

 

mxmlc -debug Main.as

 

Опция -debug нужна, чтобы нормально работала функция trace(). Путь к компилятору mxmlc нужно добавить в переменную PATH, либо указывать полный путь к бинарнику компилятора. В данный момент, в Flex4 SDK компилятор располагается в подкаталоге /bin каталога, куда был установлен Flex4 SDK.

 

Вот что в результате должно получиться:

 

 

Исходники проекта: flash_image_view.zip

 

 



К списку "Компьютерное"

Поделиться этой страницей


Статистика


RSS подписка

Подпишитесь на новости сайта по RSS


 WebHamster.Ru
 Домик любопытного хомячка
Яндекс индекс цитирования
Почтовый ящик