波紋+環境マップ
波紋+環境マップ
マウスカーソルの位置に波が起きる
/**
* Copyright Nao_u ( http://wonderfl.net/user/Nao_u )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/sabs
*/
// forked from Nao_u's テクスチャ生成実験
//
// 波紋+環境マップ
//
// マウスカーソルの位置に波が起きる
//
package {
import flash.display.Sprite;
import flash.events.*;
[SWF(width="465", height="465", backgroundColor="0xFFFFFF", frameRate="60")]
public class FlashTest extends Sprite {
public function FlashTest() {
Main = this;
startLoad();
stage.addEventListener(Event.ENTER_FRAME,update);
}
}
}
import flash.display.*;
import flash.events.*
import flash.text.TextField;
import flash.geom.*;
import flash.utils.getTimer;
import flash.ui.Keyboard;
import flash.net.*;
var Main:Sprite;
var SCREEN_W:Number = 465;
var SCREEN_H:Number = 465;
var Text:TextField
var Tex:ProcTex;
var BITMAP_W:int = 465/2;
var BITMAP_H:int = 465/2;
var TexData: BitmapData;
var loaderA:Loader;
var loaderB:Loader;
var bLoad:Boolean = false;
function startLoad():void{
loaderA = new Loader();
loaderA.load( new URLRequest("http://img.f.hatena.ne.jp/images/fotolife/N/Nao_u/20090913/20091231171735.jpg") );
loaderA.contentLoaderInfo.addEventListener( Event.COMPLETE, loadComplete );
}
function loadComplete(e:Event):void {
loaderB = new Loader();
loaderB.contentLoaderInfo.addEventListener(Event.INIT, initialize);
loaderB.loadBytes(loaderA.contentLoaderInfo.bytes);
}
function initialize(event:Event):void {
var loader:Loader = loaderB;
TexData = new BitmapData(loader.width, loader.height, false);
TexData.draw(loader);
Tex = new ProcTex( BITMAP_W, BITMAP_H );
Tex.Bmp.x = 0;
Tex.Bmp.y = 0;
Text = new TextField();
Text.text = "----";
Text.autoSize = "left";
Main.addChild(Text);
bLoad = true;
}
// 更新
var mxPrev:int;
var myPrev:int;
var Pow:Number = 1.0;
function update(e :Event):void{
var time:int = getTimer();
Tex.draw();
var mx:int = Main.mouseX * BITMAP_W / SCREEN_W;
var my:int = Main.mouseY * BITMAP_H / SCREEN_H;
Pow += Math.abs(mx - mxPrev) + Math.abs(my - myPrev);
if( Pow > 1.0 ) Pow = 1.0;
Tex.addPower( mx, my, Pow );
Pow *= 0.5;
mxPrev = mx;
myPrev = my;
var endTime:int = getTimer() - time;
Text.text = " 生成時間:" + endTime + "[ms]";
}
// テクスチャ生成クラス
class ProcTex{
public var BmpData:BitmapData;
public var TmpBmpData:BitmapData;
public var Bmp:Bitmap;
public var Width:int;
public var Height:int;
public var HeightBuf:Array;
public var HeightIdxDst:int;
public var HeightIdxSrc0:int;
public var HeightIdxSrc1:int;
public var BufWidth:int;
public var BufHeight:int;
public var PixelBufSize:int = 256;
public var PixelBuf:Vector.<int>;
public function ProcTex( w:int, h:int ){
Width = w;
Height = h;
BmpData = new BitmapData(Width, Height, false, 0xffffff);
Bmp = new Bitmap(BmpData);
Bmp.scaleX = 2.0;
Bmp.scaleY = 2.0;
Main.addChild(Bmp);
// 波高バッファの生成
HeightBuf = new Array;
BufWidth = Width+2;
BufHeight = Height+2;
HeightBuf[0] = new Vector.<Number>;
HeightBuf[1] = new Vector.<Number>;
HeightBuf[2] = new Vector.<Number>;
for( var x:int=-1; x<Width+1; x++ ){
for( var y:int=-1; y<Height+1; y++ ){
var idx:int = (x+1) + (y+1)*BufWidth;
HeightBuf[0].push( 0 );
HeightBuf[1].push( 0 );
HeightBuf[2].push( 0 );
}
}
// 環境マップテクスチャバッファの生成
PixelBuf = new Vector.<int>;
for( x=0; x<PixelBufSize; x++ ){
for( y=0; y<PixelBufSize; y++ ){
var col:int = TexData.getPixel(x, y);
PixelBuf.push(col);
}
}
HeightIdxSrc0=0;
HeightIdxSrc1=1;
HeightIdxDst=2;
}
public function draw():void{
HeightIdxSrc0++;
HeightIdxSrc1++;
HeightIdxDst++;
if( HeightIdxSrc0 > 2 ) HeightIdxSrc0 = 0;
if( HeightIdxSrc1 > 2 ) HeightIdxSrc1 = 0;
if( HeightIdxDst > 2 ) HeightIdxDst = 0;
calcWave();
createBmp( HeightIdxDst );
}
// 水面に力を加える
public function addPower( px:int, py:int, pow:Number ):void{
var r:int = 6;
var buf:Vector.<Number> = HeightBuf[HeightIdxDst];
for( var lx:int=-r; lx<=r; lx++ ){
for( var ly:int=-r; ly<=r; ly++ ){
const d:Number = Math.sqrt(lx*lx+ly*ly);
if (d < r) {
var p:Number = Math.cos(Math.PI/2 * d/r);
var x:int = px + lx;
var y:int = py + ly;
if( x < 0 || x >= Width || y < 0 || y >= Height ) break;
var idx:int = (x+1) + (y+1)*BufWidth;
buf[idx] += pow * p;
}
}
}
}
// 水面画像の生成
public function createBmp( idx:int ):void{
var buf:Vector.<Number> = HeightBuf[HeightIdxDst];
var col:Number, colU:Number, colL:Number, vecX:Number, vecY:Number;
var idx:int, ix:int, iy:int;
BmpData.lock();
for( var x:int=0; x<Width; x++ ){
for( var y:int=0; y<Height; y++ ){
idx = (x+1) + (y+1)*BufWidth;
col = buf[idx];
colU = buf[idx-BufWidth];
colL = buf[idx-1];
vecX = ((colL - col)*0.55 + 1.0) *128;
vecY = ((colU - col)*0.55 + 1.0) *128;
ix = vecX; iy = vecY;
if( ix < 50 ) ix=50;
if( iy < 50 ) iy=50;
if( ix > 200 ) ix=200;
if( iy > 200 ) iy=200;
BmpData.setPixel(x, y, PixelBuf[ix+iy*PixelBufSize]);
}
}
BmpData.unlock();
}
// 波計算
public function calcWave():void{
var c1:Number = 0.50;
var c2:Number = 0.010;
var cc:Number = 1 / (1 + c2);
var srcBuf0:Vector.<Number> = HeightBuf[HeightIdxSrc0];
var srcBuf1:Vector.<Number> = HeightBuf[HeightIdxSrc1];
var dstBuf:Vector.<Number> = HeightBuf[HeightIdxDst];
var idx:int, idxU:int, idxD:int, idxL:int, idxR:int;
for( var x:int=0; x<Width; x++ ){
for( var y:int=0; y<Height; y++ ){
idx = (x+1) + (y+1)*BufWidth;
idxU = (x+1) + (y )*BufWidth;
idxD = (x+1) + (y+2)*BufWidth;
idxL = (x ) + (y+1)*BufWidth;
idxR = (x+2) + (y+1)*BufWidth;
dstBuf[idx] = ( srcBuf1[idx] *(2-4*c1) -srcBuf0[idx] * (1-c2) +
( srcBuf1[idxU] + srcBuf1[idxD] + srcBuf1[idxL] + srcBuf1[idxR]) * c1 ) * cc;
}
}
}
}