Tweensy FX という Flash/ActionScript 用のトゥイーン&モーション・エフェクトのライブラリを使って、炎と煙のエフェクトサンプルを作ってみた。
というか処理内容は、Tweensy に付属していたサンプルそのまま。

ただ、付属のサンプルコード (examples/fx/FireSmokeFX.as) はそのままだと Flex SDK + FlashDevelop で使えなかったので、その部分だけちょっと修正している。

FireSmokeFX: Tweensy FX による炎と煙のエフェクト

開発環境

OS: Windows XP
コンパイラ: Flex 3 SDK
IDE: FlashDevelop 3.0.1 RTM

Tweensyについて

Tweensy は Tweener みたいなトゥイーンアニメーションを実現するライブラリ。

Tweensy Original というライブラリが基本的なライブラリ。
これを軽くした方向へ進化したものが Tweensy Zero で、エフェクトに特化したのが Tweensy FX というライブラリらしい。

今回は tweensy - Google Code から「Tweensy 0.2.2.zip」をダウンロードして解凍。

Tweensy FX のソースコードが beta/source/cs3/fx 以下にあるので、このソースコードをまとめて FlashDevelop に読み込ませてコンパイルして使う。

FlashDevelop でのプロジェクト作成

メニューから [Project] -> [New Project] -> [AS3 Project] で新規プロジェクトを作成。

エフェクトの材料を抜き出す

「Tweensy 0.2.2.zip」には炎と煙のエフェクトサンプルコード(examples/fx/FireSmokeFX.as)が入っていたがそのまま Flex SDK + FlashDevelop でコンパイルすると実行時エラーが出てしまう。


ReferenceError: Error #1065: 変数 Flame は定義されていません。
    at global/flash.utils::getDefinitionByName()
    at FireSmokeFX()

材料となるクラスが無いのでエラーになるらしい。

そこで Adobe Flash CS4 Professional 用のサンプルファイル examples/fx/FireSmokeFX.fla からシンボル等を含むSWFファイルを書き出すことにした。

Adobe Flash CS4 Professional で FireSmokeFX.fla から SWF を書き出す

FireSmokeFXResource.swf というファイル名で出力して、FlashDevelop プロジェクトの src ディレクトリに置いた。

FireSmokeFXResource.swf in FlashDevelop

よくわかっていないけど、Adobe Flash CS4 Professional で見たシンボルの情報。

シンボルプロパティ
名前: Smoke
クラス: Smoke
基本クラス: flash.display.Sprite
タイプ: ムービクリップ

シンボルプロパティ
名前: Flame
クラス: Flame
基本クラス: flash.display.Sprite
タイプ: ムービクリップ

ビットマッププロパティ
flames0005.png
クラス: FlameBmd
基本クラス: flash.display.BitmapData

ちなみに Adobe Flash CS4 Professional は アドビ - ダウンロード から30日間限定体験版がダウンロードできる。

炎と煙のエフェクト ソースコード

元のサンプルコード examples/fx/FireSmokeFX.as を一部修正している。
主な修正箇所は getDefinitionByName でクラスを取得している部分をコメントアウトしている部分と、かわりに Embed でクラスを埋め込んでいる部分。
不思議だったのが FlameBmd クラス。このクラス使われていないように見えるのにソースコード上でわざわざ読み込んでいる。なんでだろう?


package {
  import flash.display.*;
  import flash.events.*;
  import flash.filters.BlurFilter;
  import flash.geom.ColorTransform;
  import flash.utils.getDefinitionByName;
 
  import com.flashdynamix.motion.effects.*;
  import com.flashdynamix.motion.effects.core.*;
  import com.flashdynamix.motion.extras.Emitter;
  import com.flashdynamix.motion.layers.*;
  import com.flashdynamix.utils.SWFProfiler;  
 
  // added by NI-Lab.
  [SWF(width = "550", height = "400", backgroundColor = "#000000", frameRate = "40")]
 
  /**
   * @author shanem
   */
  public class FireSmokeFX extends Sprite {
    
    // added by NI-Lab.
    [Embed(source='FireSmokeFxResource.swf', symbol='Flame')]
    private var Flame:Class;
 
    // added by NI-Lab.
    [Embed(source='FireSmokeFxResource.swf', symbol='Smoke')]
    private var Smoke:Class;
    
    private var flameEmittor : Emitter;
    private var smokeEmittor : Emitter;
    private var layer : BitmapLayer;
    private var smokeStartCt : ColorTransform;
    private var smokeEndCt : ColorTransform;
    private var fireStartCt : ColorTransform;
    private var disp : PerlinDisplacementEffect;
    private var tx : Number;
    private var ty : Number;
 
    public function FireSmokeFX() {
      SWFProfiler.init(this);
      
      layer = new BitmapLayer(550, 400, 2, 0x00FFFFFF, true);
      disp = new PerlinDisplacementEffect(275, 200, 0, -5, 2);
      disp.movement = PerlinDisplacementEffect.DIRECTION;
      
      layer.add(disp);
      layer.add(new ScrollEffect(0, -2));
      layer.add(new FilterEffect(new BlurFilter(3, 3, 1)));
      layer.add(new ColorEffect(new ColorTransform(1, 1, 1, 0.9)));
      
      smokeStartCt = new ColorTransform(-0.275, 0.05, -0.05, 1, 166, 45, -6, -50);
      smokeEndCt = new ColorTransform(-0.35, -0.25, -0.125, 1, 13, 51, 19, -200);
      
      fireStartCt = new ColorTransform(1, 0, 0.2, 1, 255, 90, 0);
      
      stage.quality = StageQuality.LOW;
      
      // comment-out by NI-Lab.
      //var Flame : Class = getDefinitionByName("Flame") as Class;
      //var FlameBmd : Class = getDefinitionByName("FlameBmd") as Class;
      //var Smoke : Class = getDefinitionByName("Smoke") as Class;
      
      flameEmittor = new Emitter(Flame, {scaleX:1, scaleY:1, rotation:"-180,180", alpha:0.3}, 4, 1, "255, 285", "30, 60", 0.5, BlendMode.ADD);
      flameEmittor.transform.colorTransform = fireStartCt;
      flameEmittor.scale = 0.5;
      
      smokeEmittor = new Emitter(Smoke, {scaleX:2.5, scaleY:2.5, rotation:"-180,180"}, 1, 1, "255, 285", "100, 200", 1);
      smokeEmittor.transform.colorTransform = smokeStartCt;
      smokeEmittor.endColor = smokeEndCt;
      smokeEmittor.scale = 0.1;
      
      layer.draw(smokeEmittor.holder);
      layer.draw(flameEmittor.holder);
      
      tx = 250;
      ty = 350;
      
      addChildAt(layer, 0);
      
      addEvent(stage, Event.ENTER_FRAME, draw);
      addEvent(stage, MouseEvent.MOUSE_MOVE, move);
    }
 
    private function move(e : MouseEvent) : void {
      tx = stage.mouseX;
      ty = stage.mouseY;
    }
 
    private function draw(e : Event) : void {
      smokeEmittor.x += (tx - smokeEmittor.x) / 4;
      smokeEmittor.y += (ty - smokeEmittor.y) / 4;
      flameEmittor.x = smokeEmittor.x;
      flameEmittor.y = smokeEmittor.y;
    }
 
    protected function addEvent(item : EventDispatcher, type : String, liststener : Function, priority : int = 0, useWeakReference : Boolean = true) : void {
      item.addEventListener(type, liststener, false, priority, useWeakReference);
    }
 
    protected function removeEvent(item : EventDispatcher, type : String, listener : Function) : void {
      item.removeEventListener(type, listener);
    }
  }
}

tags: zlashdot Flash Flash FlashDevelop Tweensy

Posted by NI-Lab. (@nilab)