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ファイルを書き出すことにした。
FireSmokeFXResource.swf というファイル名で出力して、FlashDevelop プロジェクトの src ディレクトリに置いた。
よくわかっていないけど、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)