スポンサーサイト

-------- | --:--

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

[ActionScript 3.0] DisplacementMapFilterで波紋

2007-11-16 | 20:38

画像をクリックしてしばらくするとさざなみが立ちます。そのままにしておくと波は自然に収まります。

波面用のDisplacementMapFilterを作成する部分は http://www.geocities.jp/eco21426/Flash9/study/original/006/index.html のソースをベースに作成しました。

package {
    import flash.display.*;
    import flash.events.*;
    import flash.text.*;
    import flash.filters.*;
    import flash.geom.*;
 
	import com.flashdev.bitmap.*;	
 
    [SWF(width="400", height="400", backgroundColor="#ffffff")]
    public class Wave extends Sprite{
        [Embed(source="fuji.JPG")]
            private var MyImage:Class;

        private var wmg:WaveMapGenerator;
        private var picHeight:int;
        private var picWidth:int;

        private var bm:Bitmap;
        private var dmfbmd:Bitmap;
        public function Wave():void
        {
            
            stage.frameRate = 20;
            stage.quality   = "MEDIUM";
            stage.scaleMode = "noScale";
            stage.align = StageAlign.TOP_LEFT;

            var sprImg:Sprite = new Sprite();

            // Attach image
            var disImg:Bitmap = new MyImage();
            picHeight = disImg.height;
            picWidth = disImg.width;
            var filGlow:GlowFilter = new GlowFilter(0x000000, .3, 8, 8, 1, 3, false, false);
            disImg.filters = [filGlow];
            sprImg.addChild(disImg);

            // Add reflection
            var scale:Number = 1;
            var sprReflect:Reflection = new Reflection(disImg, .8, .4, 0, 0, scale);
            sprImg.addChild(sprReflect);			
            //addChild(sprImg);

            var bmd:BitmapData = new BitmapData(sprImg.width, sprImg.height);
            bmd.draw(sprImg);

            bm = new Bitmap(bmd);

            addChild(bm);

            stage.addEventListener(MouseEvent.CLICK, function(e:*):void{
                    wmg.bomb();
                    });

            wmg = new WaveMapGenerator(disImg.width, disImg.height);
            stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);

            dmfbmd = new Bitmap()
                //addChild(dmfbmd);
        }

        private function onEnterFrame( event:Event ):void
        {
            if(wmg.strength > 0){
                var bd: BitmapData = wmg.getMap();
                var dmf: DisplacementMapFilter = new DisplacementMapFilter(
                        bd, new Point(0, bm.height*0.5+10), 
                        BitmapDataChannel.BLUE, BitmapDataChannel.BLUE, 
                        0, -20, "clamp");
                bm.filters = [dmf];


                dmfbmd.bitmapData = bd;
            }

        }
    }
}
import flash.display.*;
import flash.geom.*;
import flash.events.*;
import flash.utils.*;

internal class WaveMapGenerator{
    private var RATIO_GAP: int = 80;   // グラデーション ratio 間隔
    public  var cycle:Number = 20;       // 次の波が発生するまでのカウント
    private var _cnt:int = 0;
    private var _h:int;         // 波画面の高さ
    private var _w:int;         // 波画面の幅
    public var strength:Number = 0;

    private var _decrease:Boolean = true;

    public function WaveMapGenerator(w:int, h:int){
        _w = w;
        _h = h;
        var t:Timer = new Timer(200);
        t.addEventListener(TimerEvent.TIMER, function():void{
                trace(strength.toString());
                _cnt = (_cnt + 1) % cycle;

                //var diff:Number = Math.pow((1+Math.sin(Math.PI/2*strength)),2)*0.01;
                var diff:Number = 0.008;
                if(_decrease)
                strength -= diff;
                else
                strength += diff;

                if(strength >= 1){
                strength = 1;
                _decrease = true;
                }
                if(strength <= 0)
                strength = 0;

                if(strength >= 1.0 && _cnt == 0)
                _decrease = true;

                });
        t.start();
    }

    public function bomb():void{
        _decrease = false;
        strength = 0.05;
    }

    public function getMap():BitmapData{
        if(strength == 0)
            return null;

        // グラデーション用 matrix を作成する
        const MT_H:int = 40;
        const MT_W:int = 160;
        var mt: Matrix = new Matrix();
        mt.createGradientBox(
                MT_W, MT_H, Math.PI * (-0.5),
                (_w - MT_W) / 2, (_h - MT_H) / 2 - 10);

        // 置換マップ用グラデーションを作成する
        const FOCIAL: Number = 0.4; // グラデーションの焦点位置
        const RGB: String = "RGB";
        var sh: Shape = new Shape();
        var g: Graphics = sh.graphics;

        var r1: Number = 256 * _cnt / cycle;
        var r2: Number = r1 + RATIO_GAP;
        var r3: Number = r2 + RATIO_GAP;
        var cc: uint;

        var diff:int = 0x80+ 0x80*strength-1;

        if (r3 < 256)
        {
            // 通常処理
            g.beginGradientFill(
                    GradientType.RADIAL, [0x80, diff, 0x80], null,
                    [r1, r2, r3], mt, SpreadMethod.REPEAT, RGB, FOCIAL);
        }
        else if (r2 < 256)
        {
            // 255 を越えた分を内側に移動
            cc = int(0x7f * (r3 - 256) / RATIO_GAP*strength) + 0x80;
            g.beginGradientFill(
                    GradientType.RADIAL, [cc, 0x80, 0x80, diff, cc], null,
                    [0, r3 - 256, r1, r2, 255], mt, SpreadMethod.REPEAT, RGB, FOCIAL);
        }
        else
        {
            // 255 を越えた分を内側に移動
            cc = (0x7f * (256 - r1) / RATIO_GAP*strength) + 0x80;
            g.beginGradientFill(
                    GradientType.RADIAL, [cc, diff, 0x80, 0x80, cc], null,
                    [0, r2 - 256, r3 - 256, r1, 255], mt, SpreadMethod.REPEAT, RGB, FOCIAL);
        }

        g.drawRect(0, 0, _w, _h);

        var bd:BitmapData =  new BitmapData(_w, _h, false);
        bd.draw(sh);

        return bd;
    }
}

スポンサーサイト
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。