せいき分布 forked from: Checkmate Vol.6 Amatuer
激しくこすって分散を小さくしよう!
/**
* Copyright knd ( http://wonderfl.net/user/knd )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/soLw
*/
// forked from checkmate's Checkmate Vol.6 Amatuer
package {
import flash.display.GraphicsPathCommand;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.utils.getTimer;
/**
* 激しくこすって分散を小さくしよう!
*/
public class CheckmateAmatuer extends Sprite {
private const N:uint = 20;
private const _2N: uint = N << 1; //分割数
private const W_2:uint = 232;
private const D:Number = Number(232) / N; //x方向のプロット間隔
private const Y0:Number = 288.0;
private var pltPts:Vector.<Point> = new Vector.<Point>();
private var ctrlPts:Vector.<Point> = new Vector.<Point>();
private var prevPts:Vector.<Point> = new Vector.<Point>();
private var work:Number = 0;
private var prev1X:Number;
private var prev1Y:Number;
private var prev2X:Number;
private var prev2Y:Number;
private var mouseOut:Boolean = false;
private const C_SQ:Number = 1.0; //波の伝播速度の二乗
private const DIST:Number = 0.05; //減衰係数
private const REF:Number = 0.8; //反射係数
public function CheckmateAmatuer() {
/*
コードでエッチなものごとを描写してください。
公序良俗は守ってください。
Represent something sexual by codes.
DO NOT be offensive to public order and morals.
*/
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
pltPts[i] = new Point(0,0);
for (var i:uint = 0; i< _2N; i+=1)
{
var xc:Number = D * i ;
var xp:Number = D * (i + 0.5);
ctrlPts[i] = new Point(xc, 0);
prevPts[i] = new Point(xc, 0);
pltPts[i + 1] = new Point(xp, 0);
}
ctrlPts[i] = new Point(2 * W_2, 0);
prevPts[i] = new Point(2 * W_2, 0);
pltPts[_2N + 1] = new Point(2 * W_2, 0);
prev1X = prev2X = mouseX;
prev1Y = prev2Y = mouseY;
addEventListener(Event.ENTER_FRAME, loop);
stage.addEventListener(Event.MOUSE_LEAVE, mouseLeave);
}
private function mouseLeave(e:Event):void
{
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseExists);
}
private function mouseExists(e:MouseEvent):void
{
mouseOut = true;
stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseExists);
}
//drawPathで曲線を引く
private function draw():void
{
var commands:Vector.<int> = new Vector.<int>();
var data:Vector.<Number> = new Vector.<Number>();
commands.push(GraphicsPathCommand.MOVE_TO);
data.push(pltPts[0].x, Y0 + pltPts[0].y);
for (var i:int = 0; i <= _2N; i ++)
{
commands.push(GraphicsPathCommand.CURVE_TO);
data.push(ctrlPts[i].x, Y0 + ctrlPts[i].y, pltPts[i + 1].x, Y0 + pltPts[i + 1].y);
}
graphics.clear();
graphics.lineStyle(0, 0x333333);
graphics.drawPath(commands, data);
}
private function loop(e:Event):void
{
//マウスの加速度を力積として
if (mouseOut)
{
prev1X = prev2X = mouseX;
prev1Y = prev2Y = mouseY;
mouseOut = false;
}
var frcX:Number = mouseX - 2 * prev1X + prev2X;
var frcY:Number = mouseY - 2 * prev1Y + prev2Y;
work = 0.95 * (work + 0.3 * Math.sqrt(frcX * frcX + frcY * frcY));
prev2X = prev1X;
prev2Y = prev1Y;
prev1X = mouseX;
prev1Y = mouseY;
//分散
var tw_sgm_sq:Number = 100 - work * 0.25;
tw_sgm_sq = 2 * tw_sgm_sq * tw_sgm_sq;
var dy: Number = 0.07 * work;
var i:int;
var _x:Number;
for (i = 0; i<= _2N; i++)
{
_x = ctrlPts[i].x - W_2;
ctrlPts[i].y = - work * Math.exp( - _x * _x / tw_sgm_sq) + (i & 1 == 0? dy* Math.random(): -dy* Math.random()) ;
}
pltPts[0].y = ctrlPts[0].y;
for (i = 1; i<= _2N; i++)
{
pltPts[i].y = (ctrlPts[i-1].y + ctrlPts[i].y) * 0.5;
}
pltPts[_2N + 1].y = ctrlPts[_2N].y;
draw();
if (work > Y0)
{
removeEventListener(Event.ENTER_FRAME, loop);
for (i = 0; i<= N; i++)
{
prevPts[i].y = prevPts[_2N - i].y = ctrlPts[i].y;
}
addEventListener(Event.ENTER_FRAME, reduce);
}
}
//爆ぜる
private function reduce(e:Event):void
{
var i:int;
var nextY:Vector.<Number> = new Vector.<Number>();
//波動方程式からゴニョゴニョ
nextY[0] = ctrlPts[0].y + 1 / (1 + DIST) *
(C_SQ * (REF * ctrlPts[1].y - 2 * ctrlPts[0].y + ctrlPts[1].y) + ctrlPts[0].y - prevPts[0].y);
for (i = 1; i< _2N; i+=1)
{
nextY[i] = ctrlPts[i].y + 1 / (1 + DIST) *
(C_SQ * (ctrlPts[i - 1].y - 2 * ctrlPts[i].y + ctrlPts[i + 1].y) + ctrlPts[i].y - prevPts[i].y);
}
nextY[_2N] = ctrlPts[_2N].y + 1 / (1 + DIST) *
(C_SQ * (REF * ctrlPts[_2N - 1].y - 2 * ctrlPts[_2N].y + ctrlPts[_2N - 1].y) + ctrlPts[_2N].y - prevPts[_2N].y);
prevPts[0].y = ctrlPts[0].y;
ctrlPts[0].y = nextY[0];
var max:Number = nextY[0], min:Number = nextY[0];
pltPts[0].y = ctrlPts[0].y;
for (i = 1; i<= _2N; i++)
{
prevPts[i].y = ctrlPts[i].y;
ctrlPts[i].y = nextY[i];
pltPts[i].y = (ctrlPts[i - 1].y + ctrlPts[i].y) * 0.5;
if (nextY[i] > max) max = nextY[i];
if (nextY[i] < min) min = nextY[i];
}
pltPts[_2N + 1].y = ctrlPts[_2N].y;
draw();
if (max < 1 && min > -1)
{
removeEventListener(Event.ENTER_FRAME, reduce);
prev1X = prev2X = mouseX;
prev1Y = prev2Y = mouseY;
work = 0;
addEventListener(Event.ENTER_FRAME, loop);
}
}
}
}