// forked from paq's forked from: forked from: 水面ゆらゆら // forked from hiphi's forked from: 水面ゆらゆら // forked from cDa's 水面ゆらゆら /* どこかで見覚えがある水面 ランダムで波が起きる マウスを上下に動かすと波がぐわんぐわん起きる ぎこちないので何とかする必要あり */ package { import flash.display.*; [SWF(width="465", height="465", backgroundColor="0xFFFFFF", frameRate="30")] public class Main extends Sprite { function Main() { for(var i:int = 0; i < 3; i++) { var wave:Wave = new Wave(); wave.colors = 0xC63369+i*0x130-i*0x300000; wave.blendMode = "multiply"; wave.y = i*6; addChild(wave); var box:Box = new Box(wave); box.blendMode = "multiply"; box.x = 465/2 - 100+i*100; box.y = 50; addChild(box); } } } } 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; class Box extends Sprite { private var wave:Wave; private var vx:Number = 0; private var vy:Number = 0; private var vr:Number = 0; function Box(wave:Wave) { this.wave = wave; graphics.beginFill(wave.colors); graphics.drawRect(-30, -60, 60, 60); addEventListener(Event.ENTER_FRAME, update); } private function update(e:Event):void { vy += 0.5; var depth:Number = wave.getDepth(x, y); if(depth > 0) { vy -= depth / 50; y -= depth / 20; var slope:Number = wave.getSlope(x); if(rotation < slope) {vr += 0.2;} if(rotation > slope) {vr -= 0.2;} rotation /= 1.05; if(depth < 25) { vx += rotation/50; } vx /= 1.2; } x += vx; y += vy; rotation += vr; } } class Wave extends Sprite { public const STAGE_W:uint = 465; public const STAGE_H:uint = 465; public const NUM:uint=300; //頂点数 private const MOUSE_DIFF_RATIO:Number=1; // (0<) 大きい程マウスに反応する private const AUTO_INTERVAL:uint = 5000; //オート波が起きる間隔 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 var colors:uint; function Wave() { 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 = 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 { graphics.clear(); //それぞれの波の減衰 mouseDiff -= (mouseDiff - mouseDiffGoal)*0.3; autoDiff -= autoDiff*0.3; //------------------------------------- //波の基点 //------------------------------------- //マウス波 startIndex[0] = getIndex(mouseX); 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] ); } //------------------------------------- //中点更新 //------------------------------------- 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 { graphics.beginFill(colors, 1); graphics.moveTo(STAGE_W, STAGE_H); graphics.lineTo(0, STAGE_H); graphics.lineTo( vertexes[0].x, vertexes[0].y); graphics.curveTo( vertexes[1].x, vertexes[1].y, mdlPt[0].x, mdlPt[0].y); for(var i:uint=2; i<NUM-2; i++) { graphics.curveTo( vertexes[i].x, vertexes[i].y, mdlPt[i-1].x, mdlPt[i-1].y); } graphics.curveTo( vertexes[NUM-2].x, vertexes[NUM-2].y, vertexes[NUM-1].x, vertexes[NUM-1].y); graphics.endFill(); } private function getIndex(pos:Number):int { if(pos < 0) { pos = 0; } else if(pos > STAGE_W-2) { pos = STAGE_W-2; } //-2はみ出さないための保険 return 1+Math.floor( (NUM-2) * pos / STAGE_W ); } public function getDepth(x:Number, y:Number):Number { return y - vertexes[getIndex(x)].y; } public function getSlope(pos:Number):Number { var vl:Vertex = vertexes[Math.max(0, Math.min(getIndex(pos), NUM-2))] var vr:Vertex = vertexes[Math.max(0, Math.min(getIndex(pos), NUM-2) + 1)] return Math.atan2(vr.y - vl.y, vr.x - vl.x) * 180 / Math.PI; } } class Vertex { private static const BASE_Y:uint = 250; private static const BASE_R:uint = 10; private static const PI:Number = Math.PI; private static const FRICTION:Number = 0.1; private static const DECELERATION:Number = 0.85; private 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; function Vertex(prmID:uint, parent:Object) { theta = 360 * prmID/( parent.NUM-1) ; x = prmID * parent.STAGE_W / (parent.NUM-1); y = BASE_Y + BASE_R * Math.sin( theta * PI /180 ); } 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; amp *= DECELERATION; } } 水面ゆらゆら+箱