воскресенье, 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 для построения моделей механизмов. В дальнейшем мы будем совершенствовать наши примеры, используя существующие библиотеки.

2 комментария:

  1. Здорово! Сразу захотелось сделать паровоз!

    ОтветитьУдалить
  2. Очень даже. долго искал хорошие уроки по флеш девелоп. Чтоб и подробно и понятно было. спасибо большое!)

    ОтветитьУдалить