package { import flash.display.BitmapData; import flash.display.Sprite; import flash.display.TextField; import flash.events.Event; import flash.events.MouseEvent; import flash.util.getTimer; import flash.text.TextFormat; import flash.geom.Matrix; import flash.geom.Point; import flash.filters.DisplacementMapFilter; [SWF( backgroundColor='0', frameRate='500', height='256', width='256')] public class Main extends Sprite { [Embed(source='source.jpg')] public var Source: Class; private const double: Matrix = new Matrix( 2, 0, 0, 2, 0, 0 ); private const origin: Point = new Point(); //-- wavemap size private var xMax: int; private var yMax: int; //-- 2 wavemaps over time private var wave0: BitmapData; private var wave1: BitmapData; private var result: BitmapData; private var displace: BitmapData; private var output: BitmapData; private var mouseDown: Boolean; private var source: BitmapData; private var water: DisplacementMapFilter; //-- fps private var fpsText: TextField; private var fr: int; private var ms: int; public function Main() { stage.scaleMode = 'noScale'; xMax = stage.stageWidth >> 1; yMax = stage.stageHeight >> 1; wave0 = new BitmapData( xMax, yMax, false, 0x808080 ); wave1 = new BitmapData( xMax, yMax, false, 0x808080 ); wave0.lock(); wave1.lock(); //-- waveresult result = new BitmapData( xMax, yMax, false, 0x80 ); result.lock(); output = new BitmapData( xMax << 1, yMax << 1, false, 0x80 ); //-- displacementmap result*2 displace = new BitmapData( xMax << 1, yMax << 1, false, 0x80 ); addChild( new Bitmap( output ) ); //-- source source = new Source().bitmapData; water = new DisplacementMapFilter( displace, origin, 4, 4, 48, 48 ); mouseDown = false; //-- init fps ms = getTimer(); fr = 0; var ft: TextFormat = new TextFormat(); ft.size = 10; ft.bold = true; ft.font = 'Verdana'; fpsText = new TextField(); fpsText.autoSize = 'left'; fpsText.textColor = 0xdcdcdc; fpsText.defaultTextFormat = ft; addChild( fpsText ); //-- inject events stage.addEventListener( 'enterFrame', updateWave ); stage.addEventListener( 'mouseDown', onMouseDown ); stage.addEventListener( 'mouseUp', onMouseUp ); } private function onMouseDown( event: MouseEvent ): void { mouseDown = true; } private function onMouseUp( event: MouseEvent ): void { mouseDown = false; } private function updateWave( event: Event ): void { if( mouseDown ) { // trigger wave wave0.setPixel( mouseX >> 1, mouseY >> 1, 0xffffff ); } var x: int; var y: int = yMax - 1; var n: int; var c: int; while( --y ) { x = xMax - 1; while( --x ) { //-- wave kernel n = ( wave0.getPixel( x - 1, y ) + wave0.getPixel( x + 1, y ) + wave0.getPixel( x, y + 1 ) + wave0.getPixel( x, y - 1 ) >> 1 ) - wave1.getPixel( x, y ); //-- damp the wave n += ( 0x808080 - n ) >> 7; if( n < 0 ) n = 0; wave1.setPixel( x, y, n ); //-- draw result result.setPixel( x, y, n >> 16 ); } } displace.draw( result, double, null, null, null, true ); output.applyFilter( source, source.rectangle, origin, water ); //-- flip var wt: BitmapData = wave0; wave0 = wave1; wave1 = wt; //-- fps fr++; if( ms + 1000 < getTimer() ) { fpsText.text = fr.toString(); fr = 0; ms = getTimer(); } } } }