雲みたいなエフェクト処理をクラス化してみる
BitmapDataをつかったエフェクトを汎用化してみたくてクラス化してみた。
利用イメージは次のような感じ
// なんか読み込んだ画像 var origin:BitmapData = Bitmap( loader.content ).bitmapData as BitmapData; // なんかしらフィルタマップ画像 var mapBmp:BitmapData = new FilterMap( origin.width, origin.height ); //読み込んだ画像をエフェクトクラスに突っ込んでTweenさせる var effect:Effect = new ThresholdEffect( origin, mapBmp ); addChild( effect ); Tweener.addTween( effect, { percent:1, time:2, transition: Equations.easeInCubic } ):
エフェクトの速度とかを調整したいのでpercent値に応じてエフェクトがかかるようにしました。これによってTweenerでのイージングなどが可能になりますし、Commandとかとの連携も可能です。
汎用的にするという点で、抽象クラスをつくり、Templateメソッド的にエフェクト処理のみサブクラスに任せることにしました。
//-------------------------------------- // エフェクト本体(Templateパターン) //-------------------------------------- public class Effect extends Sprite { private var _origin:BitmapData; private var _output:BitmapData; private var _effect:BitmapData; public function Effect( origin:BitmapData, output :BitmapData = null ) { _origin = origin; _output = output ? output : new BitmapData( _origin.width, _origin.height, true, 0x0 ); addChild( new Bitmap( _output ) ); } protected var _percent:Number = 0; public function get percent():Number { return _percent; } public function set percent(value:Number):void { _percent = value; _updateEffect(); } private function _updateEffect():void{ _effect = _origin.clone(); updateEffect(_effect); _output.draw( _effect ); } // ここでエフェクト処理を何かする。 protected function updateEffect( effect:BitmapData ):void{ new IllegalOperationError("updateEffectはOverrideする必要があります。"); } } //-------------------------------------- // エフェクト本体 //-------------------------------------- public class ThresholdEffect extends Effect { private var _mapBmp:BitmapData; private static const START_PARAM:uint = 0x00; private static const END_PARAM:uint = 0xFF; public function ThresholdEffect( origin:BitmapData, mapBmp:BitmapData, output:BitmapData = null ) { super( origin, output ); _mapBmp = mapBmp; } // パーセント値に応じてエフェクトをアップデート protected override function updateEffect( effect :BitmapData ):void { var threshold:uint = Math.round( Number( END_PARAM - START_PARAM) * _percent ); effect.threshold( _mapBmp, _mapBmp.rect, new Point(), ">",threshold, 0x00, 0xFF ); } }
おそらくこの手の処理で一番めんどくさいのはむしろフィルタ用のマップだったりするので、それもクラス化しておきました。CSシリーズなどを使っている人はグレースケールのビットマップ画像を用意したほうが早いでしょう。
//-------------------------------------- // エフェクト用のフィルタBitmapData //-------------------------------------- public class FilterMap extends BitmapData { public function FilterMap( w:int, h:int ) { super( w, h, false, 0x0 ); var map:Shape = new Shape(); var gMat:Matrix = new Matrix(); gMat.createGradientBox( w, h, -45 ); map.graphics.beginGradientFill( GradientType.LINEAR, [ 0x000000, 0xFFFFFF ], [ 1.0, 1.0 ], [ 0, 255 ], gMat ); map.graphics.drawRect( 0, 0, w, h ); map.graphics.endFill(); var rnd:int = Math.round(Math.random() * 65432); this.perlinNoise( width/6, height/6, 24, rnd, true, true, 1, true ); draw( map, null, null, BlendMode.MULTIPLY ); } }
動きのサンプルとコード全文はWonderflでどうぞー