forked from: 水面ゆらゆら+箱
どこかで見覚えがある水面
ランダムで波が起きる
マウスを上下に動かすと波がぐわんぐわん起きる
ぎこちないので何とかする必要あり
// forked from nemu90kWw's 水面ゆらゆら+箱
// forked from paq's forked from: forked from: 水面ゆらゆら
// forked from hiphi's forked from: 水面ゆらゆら
// forked from cDa's 水面ゆらゆら
/*
どこかで見覚えがある水面
ランダムで波が起きる
マウスを上下に動かすと波がぐわんぐわん起きる
ぎこちないので何とかする必要あり
*/
package
{
import flash.display.*;
[SWF(width="650", height="400", 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 = 0xF6F1B2+i*0x115-i*0x100000;
wave.blendMode = "multiply";
wave.y = i*6;
addChild(wave);
var box:Box = new Box(wave);
box.blendMode = "multiply";
box.x = 650/1.6 - 70+i*110;
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 = 650;
public const STAGE_H:uint = 400;
public const NUM:uint=200; //頂点数
private const MOUSE_DIFF_RATIO:Number=1; // (0<) 大きい程マウスに反応する
private const AUTO_INTERVAL:uint = 7000; //オート波が起きる間隔 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.4, (vertexes[i-1].y+vertexes[i].y)*0.4 ) );
}
//差分
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.1;
autoDiff -= autoDiff*0.52;
//-------------------------------------
//波の基点
//-------------------------------------
//マウス波
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;
}
}