Собираем
информацию
по крупицам

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="http://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

 

 


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

Интересное на сайте


Штучки-дрючки » Самодельный диафильм

Недавно я нашел в чулане диапроектор и коробку с диафильмами, которые много лет назад засунул на самую дальнюю полку. Увидев эти коробки, я тут же всп...


Классическая анимация » Прыгающая подушка

Оборудование: Pentium-IV, Wacom Graphire3 CTE-630 Среда: Flash 8 Год: 2005   Первая и, видимо, последняя попытка нарисовать мини-мультфильм по т...


Перевод документации Ext JS 4.2 » Ext JS 4.2. Часть 2: Система классов

  Впервые в истории разработки Ext JS был проведен широкий рефакторинг, в результате которого была полностью переписана система классов. Новая ар...

RSS подписка

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


О, смотри-ка какое хорошее место. Дайте два!

Внимание!

На этом сайте разрабатывается программа MyTetra и её родственные проекты.

Доступны к просмотру следующие базы знаний:

База Xintrea (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18)

База Rarrugas (1, 2)

База Balas

База YellowRaven

База Yurons

База Lesnik757

База Shandor

База Sirrichar

 

Подробности на странице MyTetra Share.

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