// forked from mex's 【AS100本ノック】8回目:水 /* * AS100本ノック * 8回目のお題は「水」 * あなたなりの「水」を表現してください。 */ //↓cda244さんの水面ゆらゆら //http://wonderfl.net/code/4c69cea8a30ffe8449400323c4f4431cd2c1ef85 //とQuasimondさんのAquaGalss Effect(AS) //http://www.quasimondo.com/archives/000561.php //を使わせてもらってます。オリジナルの部分はほとんどありません。 //すいません。ありがとうございます。 package { import caurina.transitions.Tweener; import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.BlendMode; import flash.display.GradientType; import flash.display.Loader; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.events.TimerEvent; import flash.filters.BevelFilter; import flash.filters.BlurFilter; import flash.filters.DisplacementMapFilter; import flash.filters.DropShadowFilter; import flash.geom.ColorTransform; import flash.geom.Matrix; import flash.geom.Point; import flash.geom.Rectangle; import flash.net.URLRequest; import flash.utils.Timer; import flash.system.LoaderContext; public class FlashTest extends Sprite { private const imgURL:String = "http://assets.wonderfl.net/images/related_images/2/28/2829/2829f459079fe1f1e7dc4c9a220ff2f015104ba7" public const W:int = 465; public const H:int = 465 private const PADDING:int = 10; private const ZERO:Point = new Point(0, 0); private var mat:Matrix; private const RECT:Rectangle = new Rectangle(0, 0, W, H); private var displaceFilter:DisplacementMapFilter; private var blurFilter:BlurFilter; private var base:Loader; private var baseBMD:BitmapData; private var drop:Sprite; private var drop2:Bitmap; private var drop3:Sprite; private var tempMap:BitmapData; private var displaceMap:BitmapData; private var mergeMap:BitmapData; //// public const NUM:uint=300; //頂点数 private const MOUSE_DIFF_RATIO:Number=1; // (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; private var mouseDiffGoal:Number= 0; private var autoTimer:Timer; private var autoDiff:Number = 0; //// public function FlashTest() { blurFilter = new BlurFilter(2, 2, 1); //mat = new Matrix(1, 0, 0, 1, PADDING * 0.5, PADDING * 0.5); mat = new Matrix(1, 0, 0, 1,0,0); base = new Loader(); base.contentLoaderInfo.addEventListener(Event.COMPLETE, onBaseLoaded); var context:LoaderContext = new LoaderContext(true); base.load(new URLRequest(imgURL),context); //// 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 > H){ mouseNewY = H; } mouseOldY = mouseNewY; } /*-----------------------------------------// //onBaseLoaded //------------------------------------------*/ private function onBaseLoaded(evt:Event):void { this.addChild(base); baseBMD = new BitmapData(W, H, true, 0x0000ff); var mat:Matrix = new Matrix(); mat.scale(1.05, 1.05); mat.translate(-12,-12) baseBMD.draw(base,mat); //drop drop = new Sprite(); drop.graphics.beginFill(0x808080); drop.graphics.drawCircle(25, 25, 25); //drop.graphics.drawRect(25,400,100,100); drop.graphics.endFill(); drop.alpha = 0.7; this.addChild(drop); //tempMap = new BitmapData(drop.width + PADDING, drop.height + PADDING, true, 0x00808080); tempMap = new BitmapData(W,H,true, 0x00808080); //displaceMap = new BitmapData(drop.width + PADDING, drop.height + PADDING, false, 0x00808080); displaceMap = new BitmapData(W, H, false, 0x00808080); //mergeMap = new BitmapData(drop.width + PADDING, drop.height + PADDING, true, 0x00808080); mergeMap = new BitmapData(W,H, true, 0x00808080); makeDrop(); drop2 = new Bitmap(mergeMap); drop2.filters = [new DropShadowFilter(4, 45, 0x000000, 0.02, 8, 8, 0.3, 3, false, false, false)]; this.addChild(drop2); //// addEventListener(Event.ENTER_FRAME, updateMouseDiff); addEventListener(Event.ENTER_FRAME, updateWave); autoTimer = new Timer(AUTO_INTERVAL); autoTimer.addEventListener(TimerEvent.TIMER, generateAutoWave); autoTimer.start(); //Tweener.addTween(displaceFilter, { scaleX:0, scaleY:0, time:5 }); } /*-----------------------------------------// //mouseDownHandler //------------------------------------------*/ private function mouseDownHandler(evt:MouseEvent):void { drop.graphics.lineStyle(10, 0x808080, 1); drop.graphics.beginFill(0x808080); //drop.graphics.drawCircle(mouseX, mouseY, 25 * Math.random() + 10); drop.graphics.lineTo(mouseX, mouseY); drop.graphics.endFill(); makeDrop(); /*drop3.graphics.beginFill(0x808080); drop3.graphics.drawCircle(mouseX, mouseY, 5); drop3.graphics.endFill();*/ } private function makeDrop():void { displaceFilter = new DisplacementMapFilter (displaceMap, ZERO,0, 1,12, 12,"wrap"); var bevel:BevelFilter = new BevelFilter (10, 10, 0xffffff,1, 0x000000, 1, 4,4, 3, 1, "inner"); drop.filters = [bevel]; tempMap.fillRect (tempMap.rect,0x00808080); tempMap.draw (drop, mat, new ColorTransform (1, 0, 0, 1, 0, 0, 0, 0), "normal", null, true); bevel.angle += 90; drop.filters = [bevel]; tempMap.draw (drop,mat,new ColorTransform (0, 1, 0, 1, 0, 0, 0, 0),"add",null,true); tempMap.applyFilter (tempMap,tempMap.rect,ZERO,blurFilter); displaceMap.draw (tempMap); } /*-----------------------------------------// //enterFrameHandler //------------------------------------------*/ private function enterFrameHandler(evt:Event):void { var rect:Rectangle = new Rectangle (0,0, W,H); mergeMap.copyPixels (baseBMD,rect,ZERO); rect.x = rect.y = 0; mergeMap.applyFilter (mergeMap,rect,ZERO,new BlurFilter (2,2, 2)); mergeMap.applyFilter (mergeMap,rect,ZERO,displaceFilter); mergeMap.copyChannel (tempMap,tempMap.rect,ZERO,8,8); } //// private function generateAutoWave(tEvt:TimerEvent):void { autoDiff = 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 > H){ mouseNewY =H; } mouseDiffGoal = (mouseNewY - mouseOldY) * MOUSE_DIFF_RATIO; } //--------------------------------------- // 各種更新 //--------------------------------------- private function updateWave(evt:Event):void { drop.graphics.clear(); //それぞれの波の減衰 mouseDiff -= (mouseDiff - mouseDiffGoal)*0.3; autoDiff -= autoDiff*0.3; //------------------------------------- //波の基点 //------------------------------------- //マウス波 var mX:int = mouseX; if(mX < 0){ mX = 0; } else if(mX > W-2){ mX = W-2; } //-2はみ出さないための保険 startIndex[0] = 1+Math.floor( (NUM-2) * mX / W ); 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].uodatePos( 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(); mergeMap.copyPixels (baseBMD,RECT,ZERO); mergeMap.applyFilter (mergeMap,RECT,ZERO,new BlurFilter (2,2, 2)); mergeMap.applyFilter (mergeMap,RECT,ZERO,displaceFilter); mergeMap.copyChannel (tempMap,tempMap.rect,ZERO,8,8); } //--------------------------------------- // 描画 //--------------------------------------- private function drawWave():void { drop.graphics.beginFill(0x808080, 1); drop.graphics.moveTo(W, H); drop.graphics.lineTo(0, H); drop.graphics.lineTo( vertexes[0].x, vertexes[0].y); drop.graphics.curveTo( vertexes[1].x, vertexes[1].y, mdlPt[0].x, mdlPt[0].y); for(var i:uint=2; i<NUM-2; i++){ drop.graphics.curveTo( vertexes[i].x, vertexes[i].y, mdlPt[i-1].x, mdlPt[i-1].y); } drop.graphics.curveTo( vertexes[NUM-2].x, vertexes[NUM-2].y, vertexes[NUM-1].x, vertexes[NUM-1].y); drop.graphics.endFill(); makeDrop(); } } } class Vertex { static const BASE_Y:uint = 350; 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 = 2; 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) ; x = prmID * parent.W / (parent.NUM-1); y = BASE_Y + BASE_R * Math.sin( theta * PI /180 ); } public function uodatePos(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; amp *= DECELERATION; } } forked from: 【AS100本ノック】8回目:水