In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

forked from: 水面。画像がゆがむはずだが・・・

水面を作成する。
@author SIBA
// forked from siba2260's 水面。画像がゆがむはずだが・・・
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;
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.system.LoaderContext;
	import flash.system.Security;
	import flash.net.URLRequest;

	
	[SWF(width=800, height=600, backgroundColor=0xAADDFF)]

	/**
	 * 水面を作成する。
	 * @author SIBA
	 */
	public class Main03 extends Sprite
	{	
		// ----------------------------
		//	定数
		// ----------------------------
		
		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.RED;
			dmf = new DisplacementMapFilter(null, new Point(), channel, channel, 50, 50, DisplacementMapFilterMode.COLOR)
			
			// 画像の配置
			Security.loadPolicyFile("http://farm2.static.flickr.com/crossdomain.xml"); 
			var context:LoaderContext = new LoaderContext(true);
			var loader:Loader = new Loader();
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
			loader.load(new URLRequest("http://farm4.static.flickr.com/3180/3115974098_d1b27674ef.jpg?v=0"), context);
			

			// 水面を表示するための画像を作成
			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;
				}
			}
			
		}


		// ----------------------------
		//	内部メソッド
		// ----------------------------
		
		/**
		 * 波を立てる。
		 * @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 onComplete(event:Event):void {
			var loaderInfo:LoaderInfo = event.currentTarget as LoaderInfo;
			var loader:Loader = loaderInfo.loader;
			var bmp:BitmapData = new BitmapData(loader.width, loader.height, true, 0x00FFFFFF);
			bmp.draw(loader);
			var image:Bitmap = new Bitmap(bmp);
			image.x = 400 - image.width/2;
			image.y = 300 - image.height/2;
			objectLayer.addChild(image);

			addEventListener(Event.ENTER_FRAME, onEnterFrame);
			stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
		}
		
		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];
		}
		
	}
}