水面のエフェクト
またまたwonderflでForkしてみた。
最近、wonderflのプログラムを見て勉強しているので、
こんなことばっかりしています。
水面のようなものを作成するのがあったので、
それを使いました。
Forkする前はこんな感じです。
wonderfl build flash online | 面白法人カヤック
水面のようなものが表示できていてすごいなって思いました。
でも、もっと水面っぽく見せるために
透明度も付ければいいんじゃないか?
と思い、透明度をつけて実装しました。
それがこれです。
wonderfl build flash online | 面白法人カヤック
水面の下に画像を表示し、
DisplacementMapFilterを使ってゆがむようにしました。
ソースで一部わからないところがあるんですが、
誰か教えてくれないでしょうか?
波の伝播を処理している部分なのですが・・・。
field1[xx][yy] = (field2[xx][yy] * (2 - 4 * C1) - field1[xx][yy] * (1 - C2) + (field2[xx][yy+1] + field2[xx][yy-1] + field2[xx-1][yy] + field2[xx+1][yy]) * C1) * CC;
これは何か波の公式でこの様になっているんですかね??
この部分についてだけが、分からなくて困っています。。。
一応、ソースも載せておきます。
package { import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.BitmapDataChannel; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.filters.DisplacementMapFilter; import flash.filters.DisplacementMapFilterMode; import flash.geom.Matrix; import flash.geom.Point; [SWF(width=800, height=600, backgroundColor=0xAADDFF)] /** * 水面を作成する。 * @author SIBA */ public class Main03 extends Sprite { [Embed(source="images/test.jpg")] private var P1:Class; private var image:Bitmap = new P1(); private const C1:Number = 0.5; private const C2:Number = 0.005; private const CC:Number = 1 / (1 + C2); private const SCALE:int = 10; private const FIELD_SIZE_X:int = 800 / SCALE + 2; private const FIELD_SIZE_Y:int = 600 / SCALE + 2; private var map:Bitmap; // 水面の画像 private var bitmapData:BitmapData; // 水面のデータ private var field1:Array = []; // 前回の水面データ private var field2:Array = []; // 現在の水面データ private var dmf:DisplacementMapFilter; // 水面のゆがみを作るFilter private var woterLayer:Sprite = new Sprite(); // 水面のレイヤ private var objectLayer:Sprite = new Sprite(); // オブジェクトのレイヤ public function Main03() { // レイヤーの配置 addChild(objectLayer); addChild(woterLayer); objectLayer.graphics.drawRect(0, 0, 800, 600); // 水面の揺らぎを作るためのFilterを作成 var channel:int = BitmapDataChannel.ALPHA; dmf = new DisplacementMapFilter(null, new Point(), channel, channel, 50, 50, DisplacementMapFilterMode.COLOR) // 画像の配置 image.x = stage.stageWidth/2 - image.width/2; image.y = stage.stageHeight/2 - image.height/2; objectLayer.addChild(image); // 水面を表示するための画像を作成 bitmapData = new BitmapData(FIELD_SIZE_X, FIELD_SIZE_Y, true, 0xFFFFFFFF); map = new Bitmap(bitmapData); map.scaleX = SCALE; map.scaleY = SCALE; woterLayer.addChild(map); // フィールドの初期化 for (var i:int=0; i<FIELD_SIZE_X; i++) { field1[i] = []; field2[i] = []; for (var j:int=0; j<FIELD_SIZE_Y; j++) { field1[i][j] = 0.0; field2[i][j] = 0.0; } } addEventListener(Event.ENTER_FRAME, onEnterFrame); stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); } /** * 波を立てる。 * @param px 波を立てる位置(x座標) * @param py 波を立てる位置(y座標) * @param power */ private function put(px:Number, py:Number, power:Number):void { // 立てる波の情報 const r:uint = 5; const beginX:int = (px - r < 1) ? 1 : px - r; const endX:int = (px + r > FIELD_SIZE_X - 1) ? FIELD_SIZE_X - 1 : px + r; const beginY:int = (py - r < 1) ? 1 : py - r; const endY:int = (py + r > FIELD_SIZE_Y - 1) ? FIELD_SIZE_Y - 1 : py + r; // 波の起点を作成 for (var xx:int=beginX; xx<endX; xx++) { for (var yy:int=beginY; yy<endY; yy++) { const d:Number = Point.distance(new Point(px, py), new Point(xx, yy)); if (d < r) { var p:Number = power * Math.cos(Math.PI/2 * d/r); field1[xx][yy] += p; field2[xx][yy] += p; } } } } private function onMouseMove(event:MouseEvent):void { put(event.stageX/SCALE, event.stageY/SCALE, 15); } private function onEnterFrame(event:Event):void { // 初期化 var xx:int = 0; var yy:int = 0; // 波を描く bitmapData.lock(); for (xx=1; xx<FIELD_SIZE_X; xx++) { for (yy=1; yy<FIELD_SIZE_Y; yy++) { var c:uint = Math.abs(field2[xx][yy]); var a:uint = (c + 32 > 255) ? 255 : c + 32; var r:uint = (c + 128 > 255) ? 255 : c + 128; var g:uint = (c + 160 > 255) ? 255 : c + 160; var b:uint = (c + 192 > 255) ? 255 : c + 192; bitmapData.setPixel32(xx-1, yy-1, (a << 24) | (r << 16) | (g << 8) | b); } } bitmapData.unlock(); // 波の動きを計算 for (xx=1; xx<FIELD_SIZE_X-1; xx++) { for (yy=1; yy<FIELD_SIZE_Y-1; yy++) { field1[xx][yy] = (field2[xx][yy] * (2 - 4 * C1) - field1[xx][yy] * (1 - C2) + (field2[xx][yy+1] + field2[xx][yy-1] + field2[xx-1][yy] + field2[xx+1][yy]) * C1) * CC; } } // 次へ const temp:Array = field1; field1 = field2; field2 = temp; // 全体に水面エフェクト var tempBmp:BitmapData = new BitmapData(map.width, map.height, true, 0x00FFFFFF); var mat:Matrix = new Matrix(); mat.scale(map.scaleX, map.scaleY); tempBmp.draw(map, mat); dmf.mapBitmap = tempBmp objectLayer.filters = [dmf]; } } }