TweensyFX AlianRainFXを詳しく
- 2009 年 9月 2 日
次期トゥイーンエンジンについてそろそろ真剣にやっておこうと思う次第。
ちまたでよく話題に上がるトゥイーンエンジンは、TweensyとBetweenAS3だと思います。
どっちも使いこなせるようにしておけって話ですが、同じような機能のものをいくつも覚えるのも正直シンドイですわ。
なんでとりあえず、どちらかに絞りたい。それがメインストリームになってくれることを願いつつ。
比べてみて個人的には開発中とはいえトゥイーン機能、パフォーマンスともBeTweenAS3の方がいいのかなぁという印象。あと何よりBeTweenAS3はあのSperk Projectの主催者が開発されているエンジン。こちらを支持しなくちゃ日本人じゃナイ!
ということで、僕的にはトゥイーン機能についてはBeTweenAS3に乗り換え準備中ですが、TweensyについてはFXの機能がこちらも開発中ながら気になるところ。
FXの中身をみてみると、エフェクトはFlashにビルトインのフィルター機能や変形機能を扱いやすいようにしたAPIが用意されている感じ。エフェクトを作るのに便利そうだ。
FXの使い方というよりこの変形の組み合わせ手法そのものは知っておくと応用も効くだろうし興味のあるところなので少しづつ調べてみようと思います。その中でTweensyについてもわかってくるでしょう。
手始めにAlienRainFXのサンプルを調べてみる。
見たところ多重にエフェクトを適用したBitmapを出力している模様。エフェクト用のクラスが用意されていて、このクラスはフィルタだったりカラーだったりを適用する為のAPIとして機能しているっぽい。
AlienRainFXでは、このエフェクトを統括してBitmapに描画しているのがBitmapLayerクラス。
自分的にはこの仕組みをPhotoShopに置き換えて、BitmapLayerがレイヤー。エフェクトがレイヤー効果って感じで考えるとすんなり入ってきた。
AlienRainで使われているエフェクトは、
PerlinDisplacementEffect PerlinNoiseで置き換えマップフィルターを適用するクラス
ColorEffect ColorTransFormを適用するクラス
DrawEffect Bitmapに表示オブジェクトを転写するクラス
更にエフェクトとは別にBitmapLayerにGlowFilterを適用。
DrawEffectで転写している表示オブジェクトをアニメーション。
って流れになっていて、
これだけ見ると、トゥイーンエンジンとしてTweensyはどこに使われるのって感じだけれど、AlienRainFXに関しては、転写している表示オブジェクトをアニメーションさせるところに使われている。
アニメーションするオブジェクトが20個あって、かつ無限にループ再生しているのだが、複数オブジェクトを動かすにあたって、パフォーマンスよくまとめてトゥイーンさせるTweensyGroupっていうクラスがある。リピートやランダムに値を設定できるところもTweenerに比べると楽なところだね。
でもまぁこの部分のトゥイーン自体は他のエンジンでもよいでしょう。TweensyFXが為にTweensyに縛られる必要はないって感じ。Tweensyのトゥイーン機能自体は解説ページが沢山あるのでここでは触れずエフェクトの手法に絞って見てみます。
エフェクトの流れを分解してみたのがこちら。技法を知らなきゃ出てくる訳も無いが、表現の引き出しは増やしたいならこういう発想自体が重要なんだよなぁと思う。精進せねば…。
各箇所の仕組みをAPIドキュメントから読み取ってみた。
■BitmapLayer
Bitmapを拡張したクラス。
エフェクトを管理しエフェクトを適用したBitmapを生成する。
BitmapLayer(width:Number = 500, height:Number = 500, scale:Number = 1, bgColor:uint = 0x00FFFFFF, transparent:Boolean = true, smoothing:Boolean = false)
width:Number = ビットマップの幅
height:Number = ビットマップの高さ
scale:Number = ビットマップのスケール
bgColor:uint = ビットマップの背景色
transparent:Boolean = 透明の有効・無効
smoothing:Boolean = スムージング有効・無効
- コンストラクタの引数ではBitmapのBitmapDataを初期化する値を設定する。
- エフェクトを追加する時、このBitmapDataを基準に設定すべき値が出てくるので、scaleはちょっとくせ者な気がする。背景が白透明でデフォルトっていうのも頭にいれておく。
■プロパティ
プロパティ名まんまのところは割愛して気になったところだけ。
-
list : Array
- エフェクトを格納する配列。
- この配列にエフェクトを追加していって、配列の頭から順にエフェクトを加えていったBitmapが最終的に出力されている。
-
clearOnRender : Boolean
- この値がtrueだとエフェクトを適用する最初のステップでBitmapDataを背景色で塗りつぶす模様。
■メソッド
こちらも割愛して気になったところだけ。
-
add(effect:IEffect):IEffect
- エフェクトを追加listに追加する
-
clear():void
- listを空にする。
-
dispose():void
- stopRender()を実行。
- listを空にする。
-
draw(instance:IBitmapDrawable, matrix:Matrix = null, rectangle:Rectangle = null, colorTransform:ColorTransform = null, blendMode:String = “normal”):DrawEffect
- Bitmapに転写するエフェクトをlistに追加する。
- 通常なら最終的に描く対象を渡す感じになるのかな。
- イメージ的にはPhotoShopのレイヤーに描いた塗りって感じ。
-
item(index:int):IEffect
- listの配列番号indexのエフェクトを返す。
-
remove(effect:IEffect):Boolean
- listからeffectのエフェクトを削除する。
-
render(e:Event = null):void
- Bitmapに描画する。
- このメソッドを実行するとlistのエフェクトを順番にBitmapDataに適用してBitmapの表示が更新される。
- 引数のeは現状使っていない模様。今後renderが実行された時に渡した値でイベントを発行するとかにするのかなぁ?
-
startRender():void
- EnterFrameイベントでrenderを実行する。
- インスタンスを作った時、コンストラクタで自動的に実行される。
-
stopRender():void
- startRenderで実行したEnterFrameイベントを削除。
続いてlistに加えているエフェクトを見てみる。
■PerlinDisplacementEffect
- PerlinNoiseで置き換えるエフェクト。
- DisplacementEffectを継承している。
-
DisplacementEffectは置き換えマップフィルターを生成するクラス。
さらにDisplacementEffectはFilterEffectってクラスを継承している。
要はPerlinDisplacementEffectを設定することで置き換えマップフィルターとフィルターの適用をラクチンに出来るようにしてくれる訳ですね。 -
PerlinNoiseで連続する雲模様を作ってその模様で置き換えることでゆらゆら煙りみたいな効果をつけている。
PerlinNoiseはいろいろ応用の利く手法だなぁと常々思った。これは使えそうなテクニック。
PerlinNoiseと置き換えマップフィルターについてはドキュメント参照。
参考
DisplacementMapFilter
perlinNoise()
■ColorEffect
- BitmapDataのcolorTransformプロパティに任意のColorTransFormを適用するエフェクト。
- このエフェクトがやってること自体はなんてことないわけだけれど、このサンプルみたいに、毎コマ、アルファを乗算するColorTransFormを適用して、徐々に消えていく軌跡を表示する手法は覚えておいてよさそう。
■DrawEffect
- BitmapDataにdrawをするエフェクト。
- 上記のPerlinDisplacementEffectとColorEffectはそれぞれ、フィルタを適用する、colorTransformを適用するって動作な訳で実際に描くものがなければ何も表示されない。なのでこのDrawEffectを追加するして描く訳です。
- DrawEffectには描くDisplayObjectを渡す。
AlienRainFXではこのDisplayObjectの中でグラフィックを20個動かし続けている。
最後にグラフィックを動かすTweensyのモーション
var Box : Class = getDefinitionByName("Box") as Class; var item : Sprite = new Box(); item.y = -100; item.x = (Math.random() * 400) - 20; item.scaleX = item.scaleY = 3 + (Math.random() * 3); item.blendMode = (Math.random() > 0.5) ? BlendMode.ADD : BlendMode.HARDLIGHT; var ct : ColorTransform = new ColorTransform(); ct.redOffset = 50 + (25 * Math.random()); ct.greenOffset = 150 + (50 * Math.random()); item.transform.colorTransform = ct; var tl : TweensyTimeline = tween.to(item, {scaleX:'3', scaleY:'3', y:"400, 500", x:"-10, 10"}, 1 + Math.random() * 0.5, Linear.easeNone, Math.random() * 2); tl.delayEnd = 1 + Math.random(); tl.repeatType = TweensyTimeline.REPLAY; holder.addChild(item); |
TweenGroupのインスタンスにトゥイーンを加えると、動作上まとめてトゥイーンされるっぽい。
動かすものが複数ある場合にパフォーマンス向上が期待出来ると思います。
Tweensy.toは今ある位置からのトゥイーン。TweenerのaddTweenと同じ動作ね。
パラメーターの指定の仕方で相対値移動やランダムが指定できる。
scaleX:'3', scaleY:'3' |
「’ ’」を使って指定値を囲むと、指定値を加えた値までトゥイーンする。
この場合、元のscaleX、scaleYに3を加えた値までトゥイーンする。
y:"400, 500" |
「’ ‘」を使って「,」区切りの値を囲んだ場合、区切られた値の範囲でランダムな値を加えトゥイーンする。
トゥイーンの時間と開始までの遅延がランダムに設定されていて、その下の
tl.delayEnd = 1 + Math.random(); tl.repeatType = TweensyTimeline.REPLAY; |
は、tl.delayEndで値がトゥイーンし終わった後にトゥイーン完了までの遅延を設定できる。
tl.repeatType = TweensyTimeline.REPLAY;で無限にループ出来る。
この辺はTweenerだとメンドくさかったところだなぁ。