[转]小日本写的模拟波浪的波动图,可以抽象出來做雙疊波

http://bbs.9ria.com/viewthread.php?tid=71325&extra=page%3D1%26amp;orderby%3Ddateline%26amp;filter%3D86400

這個波形算法的抽象原型可以寫成類結構
package wave {
        import flash.display.Sprite;
        import flash.display.StageAlign;
        import flash.display.StageScaleMode;
        import flash.events.Event;
        import flash.events.TimerEvent;
        import flash.utils.Timer;
        import flash.utils.getTimer;
        import flash.geom.Point;

        public class Wavef extends Sprite {
                public var STAGE_W:uint;
                public var STAGE_H:uint;
                public var oriPointA:Point;
                public var oriPointB:Point;

                public const NUM:uint=200;//頂点数
                protected var MOUSE_DIFF_RATIO:Number=.2;// (0<) 大きい程マウスに反応する--波动的比率
                private const AUTO_INTERVAL:uint=3000;//オート波が起きる間隔 msec
                private var vertexes:Array=[];//頂点
                private var mdlPt:Array=[];//頂点の中点
                //頂点の基本波からの位相差分
                // 0:マウス
                // 1:オート
                private var diffPt:Array=[[],[]];// 鼠标推动后,在原先的位相上所要增加的位相值。
                                                 // 二维数组中,第一个数组存储根据鼠标拖动后产生的位相差,第二个存储自动产生的波动的位相差。
                //波が起こるインデックス
                // 0:マウス
                // 1:オート
                private var startIndex:Array=[0,0];
                private var mouseOldY:int;
                private var mouseNewY:int;
                private var mouseDiff:Number=0;//mouseDiffGoal的缓冲
                private var mouseDiffGoal:Number=0;//鼠标拖动后产生的位相差
                private var autoTimer:Timer;
                private var autoDiff:Number=0;//计时器自动生成的位相差
                public function Wavef ( w:int = 800 , h:int = 300 ):void {
                        STAGE_W = w;
                        STAGE_H = h;

                        oriPointA = new Point ( 0 , STAGE_H );
                        oriPointB = new Point ( STAGE_W , STAGE_H );
                        for (var i:uint=0; i<NUM; i++) {
                                var vertex:Vertex=new Vertex(i,this);
                                vertexes.push( vertex );
                                //中点作成
                                if (i>1) {
                                        mdlPt.push( new Point( (vertexes[i-1].x+vertexes[i].x)*0.5, (vertexes[i-1].y+vertexes[i].y)*0.5 ) );
                                }
                                //差分
                                diffPt[0].push( 0 );
                                diffPt[1].push( 0 );
                        }
                        mouseNewY=mouseY;
                        if (mouseNewY<0) {
                                mouseNewY=0;
                        } else if (mouseNewY > STAGE_H) {
                                mouseNewY=STAGE_H;
                        }
                        mouseOldY=mouseNewY;
                        addEventListener(Event.ENTER_FRAME, updateMouseDiff);
                        addEventListener(Event.ENTER_FRAME, updateWave);
                        autoTimer=new Timer(AUTO_INTERVAL);
                        autoTimer.addEventListener(TimerEvent.TIMER, generateAutoWave);
                        autoTimer.start();
                }
                private function generateAutoWave(tEvt:TimerEvent):void {
                        autoDiff=200;//自动生成100的位相差
                        startIndex[1] = Math.round( Math.random()*(NUM-1) );//在波形的随机位置自动产生波形抖动(产生位相差)
                }
                //--------------------------------------
                //        マウスY座標の差を計算
                //--------------------------------------
                private function updateMouseDiff(evt:Event):void {
                        mouseOldY=mouseNewY;
                        mouseNewY=mouseY;
                        if (mouseNewY<0) {
                                mouseNewY=0;
                        } else if (mouseNewY > STAGE_H) {
                                mouseNewY=STAGE_H;
                        }
                        mouseDiffGoal = (mouseNewY - mouseOldY) * MOUSE_DIFF_RATIO;//根据鼠标前后位移差设置波动起伏的位相差
                }
                //---------------------------------------
                //        各種更新
                //---------------------------------------
                private function updateWave(evt:Event):void {
                        //それぞれの波の減衰
                        mouseDiff -= (mouseDiff - mouseDiffGoal)*0.3;
                        autoDiff-=autoDiff*0.9;//波形自动波动时的速率
                        //-------------------------------------
                        //波の基点
                        //-------------------------------------
                        //マウス波
                        var mX:int=mouseX;
                        if (mX<0) {
                                mX=0;
                        } else if (mX > STAGE_W-2) {
                                mX=STAGE_W-2;
                        }//-2はみ出さないための保険
                        startIndex[0] = 1+Math.floor( (NUM-2) * mX / STAGE_W );//startIndex[0]表示波形图上,鼠标拖动的那个点,用Math.floor是
                                                                               //可以取到NUM个点里面x坐标小于当前鼠标x坐标的最大值
                        diffPt[0][startIndex[0]] -= ( diffPt[0][startIndex[0]] - mouseDiff )*0.99;
                        //自动波
                        diffPt[1][startIndex[1]] -= ( diffPt[1][startIndex[1]] - autoDiff )*0.99;
                        var i:int;
                        //------------------------------------
                        //差分更新
                        //-------------------------------------
                        //マウス波
                        //左側
                        var d:uint;
                        for (i=startIndex[0]-1; i >=0; i--) {
                                d=startIndex[0]-i;
                                if (d>15) {
                                        d=15;
                                }
                                diffPt[0][i] -= ( diffPt[0][i] - diffPt[0][i+1] )*(1-0.01*d);
                        }
                        //右側
                        for (i=startIndex[0]+1; i < NUM; i++) {
                                d=i-startIndex[0];
                                if (d>15) {
                                        d=15;
                                }
                                diffPt[0][i] -= ( diffPt[0][i] - diffPt[0][i-1] )*(1-0.01*d);
                        }
                        //オート波
                        //左側
                        for (i=startIndex[1]-1; i >=0; i--) {
                                d=startIndex[1]-i;
                                if (d>15) {
                                        d=15;
                                }
                                diffPt[1][i] -= ( diffPt[1][i] - diffPt[1][i+1] )*(1-0.01*d);
                        }
                        //右側
                        for (i=startIndex[1]+1; i < NUM; i++) {
                                d=i-startIndex[1];
                                if (d>15) {
                                        d=15;
                                }
                                diffPt[1][i] -= ( diffPt[1][i] - diffPt[1][i-1] )*(1-0.01*d);
                        }
                        //-------------------------------------
                        //各頂点更新
                        //-------------------------------------
                        for (i=0; i < NUM; i++) {
                                vertexes[i].updatePos( diffPt[0][i]+diffPt[1][i]);//更新波形上各点的位相,位相差等于鼠标抖动的和自动产生的,即为diffPt[0][i]+diffPt[1][i]
                        }
                        //-------------------------------------
                        //中点更新
                        //-------------------------------------
                        for (i=0; i < NUM-2; i++) {
                                mdlPt[i].y = (vertexes[i+1].y + vertexes[i+2].y)*0.5;//更新波形图上两点中点的位相,使波形图看起来更流畅
                        }
                        drawWave();
                }
                //---------------------------------------
                //        描画
                //---------------------------------------
                private function drawWave():void {
                        var arr:Array = [];
                        var o:Operation;
                        arr [ arr.length ] = new Operation ( Operation.CLEAR );
                        //根据存储的vertexes和mdlPt数组里的各点位相,画贝塞尔曲线
                        o = new Operation ( Operation.FILL );
                        o.color = 0xFFFFFF;
                        arr [ arr.length ] = o;
                        //填充范圍邊界點
                        o = new Operation ( Operation.MOVE );
                        o.tox = oriPointB.x;
                        o.toy = oriPointB.y;
                        arr [ arr.length ] = o;
                        //畫
                        o = new Operation ( Operation.L_TO );
                        o.tox = oriPointA.x;
                        o.toy = oriPointA.y;
                        arr [ arr.length ] = o;
                        o = new Operation ( Operation.L_TO );
                        o.tox = vertexes[0].x;
                        o.toy = vertexes[0].y;
                        arr [ arr.length ] = o;
                        o = new Operation ( Operation.C_TO );
                        o.tox = mdlPt[0].x;
                        o.toy = mdlPt[0].y;
                        o.controlx = vertexes[1].x;
                        o.controly = vertexes[1].y;
                        arr [ arr.length ] = o;

                        for (var i:uint=2; i<NUM-2; i++) {
                                o = new Operation ( Operation.C_TO );
                                o.tox = mdlPt[i-1].x;
                                o.toy = mdlPt[i-1].y;
                                o.controlx = vertexes[i].x;
                                o.controly = vertexes[i].y;
                                arr [ arr.length ] = o;
                        }
                        o = new Operation ( Operation.C_TO );
                        o.tox = vertexes[NUM-1].x;
                        o.toy = vertexes[NUM-1].y;
                        o.controlx = vertexes[NUM-2].x;
                        o.controly = vertexes[NUM-2].y;
                        arr [ arr.length ] = o;

                        o = new Operation ( Operation.CLEAR );
                        dispatchEvent ( new DrawRequest ( arr ) );
                }
               
        }
}
class Vertex {
        static const BASE_Y:uint=150;
        static const BASE_R:uint=10;
        static const PI:Number=Math.PI;
        static const FRICTION:Number=0.1;//波形抖动后回复到正常状态的速率指数
        static const DECELERATION:Number=0.95;
        static const SPEED_OF_BASE_WAVE:uint=3;
        private var theta:uint=0;
        private var goalY:Number=0;
        private var amp:Number=0;
        public var x:Number;
        public var y:Number;
        public function Vertex(prmID:uint, parent:Object):void {
                theta =  360 * prmID/( parent.NUM-1) ;//角度的弧度值。根据NUM值将舞台上分为NUM块,然后将2π的弧度分配给各块,这样舞台上平静的时候正好是一段完整的波形。
                x = prmID * parent.STAGE_W / (parent.NUM-1);
                y=BASE_Y+BASE_R*Math.sin(theta*PI/180);
        }
        //让波形不断波动的函数,不断更新各点的y坐标
        public function updatePos(diffVal:Number):void {
                theta+=SPEED_OF_BASE_WAVE;
                if (theta>=360) {
                        theta-=360;
                }
                goalY=BASE_Y+BASE_R*Math.sin(theta*PI/180);
                goalY+=diffVal;
                amp+=goalY-y;
                y+=amp*FRICTION;//y坐标以FRICTION的缓冲速率缓冲到正常状态
                amp*=DECELERATION;
        }
}
复制代码

你可能感兴趣的:(算法,PHP,Flash,360,bbs)