воскресенье, 26 декабря 2010 г.

Hello FlashDevelop. Часть 2

Будем считать, что после предыдущего урока Вы уже немного разобрались как работать с редактором FlashDevelop. Поэтому приступаем изучать возможности Flash в области визуализации физических явлений и работы механизмов. Начнем мы с довольно простого примера анимации кривошипно-ползунного механизма. Что же из себя представляет этот механизм? С его работой мы сталкиваемся каждый день – это механизм двигателя внутреннего сгорания:
Устройство двигателя внутреннего сгорания
Сначала мы изобразим этот механизм упрощенно (а в следующих уроках добавим графику).
Рассматриваемый механизм в произвольном положении
Чтобы полностью разобраться, как работает этот пример, нужно вспомнить немного тригонометрии, но обо всем по порядку.

В качестве исходных данных принимаем:
- в начальном положении поршень находится в верхней мертвой точке (ВМТ), т.е. угол φ = 0 градусов (все звенья вытягиваются в линию);
- длину кривошипа AB принимаем равной 50 пикселей;
- длину шатуна ВС принимаем равной 200 пикселей;
- скорость вращения кривошипа принимаем произвольной, например 0,1 радиан за кадр.

Для того, чтобы отобразить движение механизма, нам необходимо выразить положения его характерных точек А, В и С в зависимости от угла поворота кривошипа АВ.
Положение точки А неизменно (она неподвижна):
Координаты точки В зависят от угла поворота кривошипа AB. Выразить эту зависимость не составит труда тем, кто совсем немного помнит школьное определение синуса и косинуса в прямоугольном треугольнике:
С расчетом положения точки С немного сложнее, здесь нам поможет теорема синусов. Рассмотрим треугольник АВС, по теореме синусов имеем следующее соотношение:
 
отсюда:
Тогда, учитывая что "вертикальная" координата точки С постоянна (см. рисунок), имеем:
Теперь нам осталось лишь выразить все эти зависимости в коде:
package 
{
 // Импорт необходимых классов
 import flash.display.Sprite;
 import flash.events.Event;
 
 // Объявление класса
 public class Mechanism extends Sprite 
 {
  // Основные размеры механизма:
  //
  // Длина кривошипа АВ
  private var a:Number = 50;
  // Длина шатуна ВС
  private var b:Number = 200;
  
  // Угловые параметры, характеризующие положение механизма
  //
  // Угол поворота кривошипа
  private var phi:Number = 0;
  // Угол поворота шатуна
  private var psi:Number;

  // Угловая скорость кривошипа
  private var angularVelocity:Number = 0.1;
  
  // Положение неподвижной точки кривошипа (точки А)
  private var oporaX:Number;
  private var oporaY:Number;
  
  // Символы для отображения характерных точек механизма
  //
  // Точка А
  private var sharnirOne:Sprite;
  // Точка В
  private var sharnirTwo:Sprite;
  // Точка С
  private var sharnirThree:Sprite;
  // Ползун
  private var polzun:Sprite;
  // Конструктор класса
  public function Mechanism(oporaX:Number = 0, 
                            oporaY:Number = 0):void 
  {
   this.oporaX = oporaX;
   this.oporaY = oporaY;
   if (stage) init();
   else addEventListener(Event.ADDED_TO_STAGE, init);
  }
  
  // Инициализация класса
  private function init(e:Event = null):void 
  {
   removeEventListener(Event.ADDED_TO_STAGE, init);
   // Расчет начального положения механизма  
   startPosition();
   // Добавление автоматического обновления состояния механизма
   addEventListener(Event.ENTER_FRAME, onEnterFrame);
  }
  
  // Расчет начального положения механизма 
  // (поршень находится в верхней мертвой точке)
  private function startPosition():void
  {
   sharnirOne = makeSharnir(oporaX, oporaY);
   addChild(sharnirOne);
   sharnirTwo = makeSharnir(oporaX + a, oporaY);
   addChild(sharnirTwo);
   polzun = makePolzun(oporaX + a + b, oporaY);
   addChild(polzun);
   sharnirThree = makeSharnir(oporaX + a + b, oporaY);
   addChild(sharnirThree);
  }

  // Расчет и отрисовка текущего положения механизма
  private function onEnterFrame(e:Event):void 
  {
   // Обновление значения угла поворота кривошипа
   phi += angularVelocity;
   // Обновление положения точки В:
   sharnirTwo.x = oporaX + a * Math.cos(phi);
   sharnirTwo.y = oporaY + a * Math.sin(phi);
   psi = Math.asin(a * Math.sin(phi) / b);
   var ac:Number = a * Math.cos(phi) + b * Math.cos(psi);
   polzun.x = oporaX + ac;
   // Обновление положения точки С:
   sharnirThree.x = oporaX + ac;
   // Очистка экрана
   this.graphics.clear();
   this.graphics.lineStyle(2, 0x000000);
   // Отрисовка звеньев АВ и ВС:
   drawStergen(sharnirOne, sharnirTwo);
   drawStergen(sharnirTwo, sharnirThree);
  }
  
  // Отрисовка ползуна
  private function makePolzun(x:Number, y:Number):Sprite
  {
   var polzun:Sprite = new Sprite();
   polzun.graphics.lineStyle(2, 0x000000);
   polzun.graphics.beginFill(0x0099ff);
   polzun.graphics.drawRect( -15, -8, 30, 16);
   polzun.graphics.endFill();
   polzun.x = x;
   polzun.y = y;
   return polzun;
  }
  
  // Отрисовка стержневых звеньев
  private function drawStergen(spr1:Sprite, spr2:Sprite):void
  {
   this.graphics.moveTo(spr1.x, spr1.y);
   this.graphics.lineTo(spr2.x, spr2.y);
  }
  
  // Отрисовка характерных точек механизма
  private function makeSharnir(x:Number, y:Number):Sprite
  {
   var sharnir:Sprite = new Sprite();
   sharnir.graphics.lineStyle(2, 0x000000);
   sharnir.graphics.beginFill(0x0099ff);
   sharnir.graphics.drawCircle(0, 0, 4);
   sharnir.graphics.endFill();
   sharnir.x = x;
   sharnir.y = y;
   return sharnir;
  } 
 }
}

Сохраните этот код в файле Mechanism.as. Вы уже можете скомпилировать данный файл (для этого в панели менеджера проекта щелкните по нему правой кнопкой мыши и в появившемся меню выберите пункт “Always Compile” и нажмите клавишу F5). Но можно пойти немного дальше – изменить положение механизма на плоскости, для этого создадим еще один класс Main, сделав его главным классом проекта:
package  
{
 import flash.display.Sprite;
 
 public class Main extends Sprite
 {
  
  public function Main() 
  {
   var mechanism:Mechanism = new Mechanism();
   
   mechanism.x = 100;
   mechanism.y = 100;
   mechanism.rotation = 45;
   
   addChild(mechanism);
  } 
 }
}

Если у Вас после компиляции видна только часть механизма, то нужно просто изменить свойства проекта. Для этого в меню Project выбираем пункт “Properties…” и в появившемся окне изменяем размеры (Dimensions) выходного файла на необходимые (у меня это 350х350 пикселей).
В итоге получим следующую картину:
Если у Вас что-то не получается или Вы не хотите набирать весь код, то можете скачать исходники к этому уроку. Кстати, если хотите попрактиковаться, то попробуйте создать анимацию вот такого механизма (свою реализацию я покажу в одном из следующих постов):
V-образный двигатель

Кстати, Вы можете найти очень много различных анимированных моделей на этой страничке, к некоторым из них есть исходники (правда они на ActionScript 1.0 и сделаны во Flash IDE)

P.S. Да, я знаю, что этот код не является универсальным и получившейся модели нужны дополнительные детали. Этим примером я хотел показать относительную простоту использования Flash для построения моделей механизмов. В дальнейшем мы будем совершенствовать наши примеры, используя существующие библиотеки.

суббота, 25 декабря 2010 г.

Hello FlashDevelop. Часть 1

1. Для начала нам понадобится скачать FlashDevelop и Flex SDK.
2. После этого устанавливаем FlashDevelop и распаковываем Flex SDK в папку “…\FlashDevelop\Tools\flexsdk” (где “…\FlashDevelop\” – это папка, в которую Вы установили сам FlashDevelop).
3. Запускаем FlashDevelop и создаем новый AS3-проект, для этого в меню Project выбираем “New Project…” и в появившемся окне выбираем пункт “AS3 Project”, в поле “Name” задаем имя проекта (пусть это будет “HelloFlashDevelop”), выбираем местоположение папки проекта, жмем “OK”. Проект создан.
Окно создания проекта
4. Справа Вы увидите панель Project, в ней отображается структура файлов и папок Вашего проекта (Если панели нет, то в меню View выбираем пункт “Project Manager”):
Менеджер проекта
Как видно, наш проект уже содержит один файл – Main.as, отмеченный зеленой стрелочкой (это означает, что это файл главного класса проекта – точка входа, с которой все начинается). Открываем этот файл, дважды щелкнув по нему в панели менеджера проекта. И вот, что данный класс уже содержит:

package 
{
    import flash.display.Sprite;
    import flash.events.Event;

    public class Main extends Sprite 
    {

        public function Main():void 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }

        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            // entry point
        }          
    }
}

В первой строке идет объявление пакета. Пакеты нужны для организации классов и отражают структуру папок, в которых они расположены. В качестве имен пакетов рекомендуется использование имен доменов, что гарантирует уникальность его имени и отсутствие конфликтов имен. Например, у Вас может быть класс Utils, расположенный в папке “ru/teormech/utils/”, тогда имя пакета будет ru.teormech.utils.
Так как при создании проекта, мы оставили поле Package пустым (см. первый скриншот), то пакет у нас безымянный:

package
{

Затем происходит импорт необходимых классов Sprite и Event:

import flash.display.Sprite;
import flash.events.Event;

Эти две строки нужны, чтобы компилятор “знал”, где искать эти классы.
Класс Sprite является базовым для любого приложения, т.к. он необходим чтобы наше приложение как-то отображалось на мониторе. Существует альтернатива в виде класса MovieClip, но его использование целесообразно при работе с Flash IDE.
Класс Event – это, как ясно из его названия, класс события. В нашем случае он нужен для реагирования на добавления приложения в список отображения.

Далее идет объявление класса Main с идентификатором доступа public, это означает, что этот класс будет доступен из любого места приложения:

public class HelloWorld extends Sprite
{

Наш класс является наследником (ключевое слово extends) класса Sprite, т.е. он будет обладать той же функциональностью, что и класс Sprite (например, можно будет его переместить на экране, отмасштабировать, нарисовать в нем что-либо и т.д.).
Заметьте, что имя класса совпадает с именем файла, в котором он находится.

Переходим далее, а далее мы видим конструктор класса – функцию, которая автоматически вызывается, когда мы создаем новый экземпляр класса (в случае с нашим главным классом, он будет создан при компиляции проекта). Имя конструктора в ActionScript должно совпадать с именем класса:

public function Main() 
{
    if (stage) init();
    else addEventListener(Event.ADDED_TO_STAGE, init);
}

Внутри конструктора происходит проверка на существование свойства stage. Если оно существует, то сразу вызывается метод init. Если свойство stage отсутствует, значит наш класс еще не был добавлен в список отображения и нам надо подождать этого события, для этого мы добавляем обработчик события Event.ADDED_TO_STAGE (что можно условно перевести как ДОБАВЛЕН_НА_СЦЕНУ):

addEventListener(Event.ADDED_TO_STAGE, init);

Когда данное событие все же происходит, то вызывается метод init (является вторым параметром метода addEventListener):

private function init(e:Event = null):void 
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
}

Метод init имеет идентификатор доступа private, т.е. он доступен только из данного класса, и никакой другой класс не может к нему обратиться. На данный момент в этом методе происходит только удаление обработчика события Event.ADDED_TO_STAGE, т.к. он больше уже не понадобится, ведь наше приложение уже готово к работе:

removeEventListener(Event.ADDED_TO_STAGE, init);

Следующая строчка // entry point – комментарий. Комментарии нужны только разработчику (в них обычно описывают логику программы на человеческом языке) и игнорируются компилятором.
Добавим после этой строки в метод init следующий код (комментарии присутствуют лишь для разъяснения):

// Создание нового  текстового поля
var myText:TextField = new TextField();
// Задание текста в текстовом поле
myText.text = “Hello FlashDevelop”;
// Добавление текстового поля в список отображения
addChild(myText);

Проверьте, появилась ли у Вас в коде строчка:

import flash.text.TextField;

Если нет, то допишите ее в начале файла (обычно FlashDevelop автоматически импортирует используемые классы):

import flash.display.Sprite;
import flash.events.Event;
import flash.text.TextField;

Теперь нажав на кнопку "Test Movie", мы запустим наш первый проект:
В появившейся флэшке должно отобразиться текстовое поле.
Если же ничего не получилось, то скачайте исходник к этому уроку и сравните его содержимое с тем, что получилось у Вас.

Я знаю, что данный урок не особенно оригинален или интересен, но это только начало. Если у Вас возникли какие-нибудь вопросы, то задавайте их в комментариях.

В качестве дополнительной справки рекомендую почитать следующие статьи:

А также, если Вы только начинаете программировать на ActionScript, то найдите какую-нибудь книгу по нему, например:
"Колин Мук - Actionscript 3.0 для Flash. Подробное руководство". Найти ее в электронном виде не составит особого труда

вторник, 21 декабря 2010 г.

Мои инструменты

Данный пост не будет особо информативным, в нем я просто хочу перечислить свои основные инструменты.
Для разработки под flash совершенно необязательно покупать достаточно дорогие программы. Если Вам не нужны навороченные средства для анимации, и Вы просто хотите немного поэкспериментировать, то можно ограничиться и такими бесплатными программами, как:

Flex SDK – бесплатный набор инструментов от компании Adobe. Сюда входит компилятор, позволяющий создавать swf-файлы, а также отладочная версия flash-плеера. В принципе, даже этого (ну и блокнота) хватит, чтобы разрабатывать под flash. Однако такой работы я никому не пожелал бы, поэтому следующим пунктом будет…

FlashDevelop - отличный редактор кода с открытым исходным кодом, поддерживающий такие языки, как actionscript 3.0, actionscript 2.0, haxe, PHP, HTML и CSS. Его основные особенности: подсветка кода, автоматические подсказка и форматирование при наборе кода и многие другие вкусности. Когда я его увидел, то не мог поверить, что такие вещи бывают бесплатными, настолько он хорош. К сожалению, работает только под Windows.

Flash – это, конечно же, графика, поэтому для рисования всяких графических элементов, которые Вы захотите вставить в свой проект, Вам могут пригодиться:

 - для редактирования растровой графики – Gimp;
 
- для редактирования векторной графики – Inkscape.
Это хоть и не Photoshop, но уже далеко не Paint. Попробуйте их.


Для редактирования звуковых файлов могу порекомендовать Вам Wavosaur.

Как видно, все перечисленные программы являются бесплатными, но это не единственное их достоинство. Надеюсь, что Вы будете их использовать (или уже используете) и убедитесь в этом.
На сегодня, думаю, хватит. В следующем посте мы установим самые необходимые программы, настроим их и начнем работать с языком actionscript, создав простенькую анимацию работы какого-нибудь несложного механизма.

воскресенье, 19 декабря 2010 г.

Первое сообщение

Вот и я завел свой блог. Здесь я постараюсь регулярно писать о своих увлечениях, связанных с технологией Adobe Flash и теоретической механикой, а также о всем, что так или иначе их касается. Надеюсь, что кто-то найдет его достаточно интересным и я найду новых друзей!