Toggle navigation
Sign Up
Log In
Explore
Works
Folders
Tools
Collections
Artists
Groups
Groups
Topics
Tasks
Tasks
Jobs
Teams
Jobs
Recommendation
More Effects...
ActionScript
// forked from Metrix's 2D Water Ripples - 2009-1-9 // Author: Richard Owen // // Based on some code i saw along time ago and I can not find now to reference // Move your mouse around the stage and check out the water trail // this works well as rain drops if you want to randomly drop points onto the surface // // Hi Richard Again // I am adding a refraction code and a background image to refract package { import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.utils.setInterval; /** * ... * @author ... */ public class Main extends Sprite { private var Water:WaterMaterial; private var intervalID:uint = 0; private var dummyBMP:flash.display.BitmapData; public function Main():void { if (stage) init(); else addEventListener(Event.ADDED_TO_STAGE, init); } private function init(e:Event = null):void { //Add backgroud pattern var size:int = 8; var gridwidth:int = 58; var gridheight:int = 58; this.graphics.clear(); this.graphics.lineStyle(1, 0x000000, 1); this.graphics.beginFill(0xFFFFFF, 1); var col:int; var row:int; col=0; row=0; row = 0; for (col = 0; col < gridwidth; col++) { for(row = 0; row < gridheight; row++){ this.graphics.drawRect(col * size, row * size, size, size); } } this.graphics.endFill(); removeEventListener(Event.ADDED_TO_STAGE, init); // entry point Water = new WaterMaterial(); stage.addChild(Water); Water.addEventListener(MouseEvent.MOUSE_DOWN, MouseClicky) Water.addEventListener(MouseEvent.MOUSE_UP, MouseRelease) Water.addEventListener(MouseEvent.MOUSE_MOVE, MouseMove) intervalID = setInterval(WaterUpdate, 15); } private function MouseClicky(event:MouseEvent):void { Water.setDrop(event.localX, event.localY); Water.setDrop(event.localX-1, event.localY+1); Water.setDrop(event.localX+1, event.localY+1); Water.setDrop(event.localX-1, event.localY-1); Water.setDrop(event.localX+1, event.localY-1); }; /* private function MouseClicky(event:MouseEvent):void { //top Water.setDrop(event.localX-2, event.localY-2); Water.setDrop(event.localX , event.localY-2); Water.setDrop(event.localX+2, event.localY-2); //left Water.setDrop(event.localX-2, event.localY-2); Water.setDrop(event.localX-2, event.localY); Water.setDrop(event.localX-2, event.localY+2); //bottom Water.setDrop(event.localX-2, event.localY+2); Water.setDrop(event.localX , event.localY+2); Water.setDrop(event.localX+2, event.localY+2); //right Water.setDrop(event.localX+2, event.localY-2); Water.setDrop(event.localX+2, event.localY); Water.setDrop(event.localX+2, event.localY+2); }; */ private function MouseMove(event:MouseEvent):void { Water.setDrop(event.localX, event.localY); }; public function WaterUpdate():void { Water.forceRefresh(); } private function MouseRelease(event:MouseEvent):void { //clearInterval(intervalID); }; } } import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.InteractiveObject; import flash.geom.Rectangle; import flash.display.Sprite; import flash.events.Event; class WaterMaterial extends Sprite { private const MaxSize:uint = 460; private const TestScale:Number = 4.0; private const BufWidth:uint = Math.floor(MaxSize / TestScale); private const BufHeight:uint = Math.floor(MaxSize / TestScale); private const MaxHeight:uint = 256; private const damping:Number = 7; private var Buffer1:Array = new Array(BufWidth); private var Buffer2:Array = new Array(BufWidth); private var tempBuff:Array; private var waterData:BitmapData; private var waterMap:Bitmap; private var dummyBMP:BitmapData; public function WaterMaterial() { addEventListener(Event.ADDED_TO_STAGE, init); } public function init(e:Event): void { removeEventListener(Event.ADDED_TO_STAGE, init); //Create a bitmap to hold the rendering data waterData = new BitmapData(BufWidth, BufHeight, true, 0x00000000); //add the water as a bitmap to the stage waterMap = new Bitmap(waterData); addChild(waterMap); // this.x = 0; this.y = 0; this.width = BufWidth * TestScale; this.height = BufHeight * TestScale; //Set all the water to a flat 0 var col:int; var row:int; for (col = 0; col < BufWidth ; col++ ) { Buffer1[col] = new Array(BufHeight); Buffer2[col] = new Array(BufHeight); for (row = 1; row < BufHeight; row++) { Buffer1[col][row] = 0; Buffer2[col][row] = 0; } } dummyBMP = new flash.display.BitmapData(500, 500); //dummyBMP.floodFill(10,10,0xff0000ff); dummyBMP.draw(root); //trace("0x"+dummyBMP.getPixel(150, 150).toString(16)); } //Add a drop of water to the pool public function setDrop(dropX:uint, dropY:uint):void { Buffer1[dropX][dropY] = MaxHeight; } //update the bitmap witht he current height private function HeightToPixel(col: int, row:int ): void { var pixelColor:uint; if(true){ pixelColor = SolidColorWater(col, row); } else { pixelColor = RefractionColor(col, row); }; waterData.setPixel32(col + 1, row + 1, pixelColor); } private function SolidColorWater(col: int, row: int): uint{ var pixelColor:uint; pixelColor = Buffer2[col][row] << 24; pixelColor = pixelColor + 0xff; return pixelColor; } private function RefractionColor(col: int, row: int): uint { var rIndex:Number; rIndex = 2.0; //Water Refraction Index var y:int; var x:int; var xDiff:int; var xAngle:Number; var xRefraction:Number; var xDisplace:Number; var yDiff:int; var yAngle:Number; var yRefraction:Number; var yDisplace:Number; var newcolor:uint; x = col; y = row; //for y := 1 to MAXY-1 do begin //for(y = 1; y < BufHeight; y++){// to MAXY-1 do begin //for x := 1 to MAXX-1 do begin //for(x=1; x
1) && (x < BufWidth - 1)) && ((y > 1) && (y < BufHeight - 1))) { xDiff = Math.floor(Buffer2[x+1][y] - Buffer2[x][y]); //yDiff := Trunc(WaveMap[x, y+1] - WaveMap[x, y]); yDiff = Math.floor(Buffer2[x][y+1] - Buffer2[x][y]); //xAngle := arctan( xDiff ); xAngle = Math.atan(xDiff); //xRefraction := arcsin( sin( xAngle ) / rIndex ); xRefraction = Math.asin(Math.sin(xAngle)/rIndex); //xDisplace := Trunc( tan( xRefraction ) * xDiff ); xDisplace = Math.floor(Math.tan(xRefraction) * xDiff); //yAngle := arctan( yDiff ); yAngle = Math.atan(yDiff); //yRefraction := arcsin( sin( yAngle ) / rIndex ); yRefraction = Math.asin( Math.sin( yAngle) / rIndex); //yDisplace := Trunc( tan( yRefraction ) * yDiff ); yDisplace = Math.floor(Math.tan( yRefraction) * yDiff); //if xDiff < 0 then begin if(xDiff < 0){ if(yDiff < 0 ){ //newcolor := BackgroundImage[x-xDisplace, y-yDisplace] newcolor = dummyBMP.getPixel32(x-xDisplace, y-yDisplace); } else { //newcolor := BackgroundImage[x-xDisplace, y+yDisplace] newcolor = dummyBMP.getPixel32(x-xDisplace, y+yDisplace); } } else { if(yDiff < 0) { //newcolor := BackgroundImage[x+xDisplace, y-yDisplace] newcolor = dummyBMP.getPixel32(x+xDisplace, y-yDisplace); } else { //newcolor := BackgroundImage[x+xDisplace, y+yDisplace] newcolor = dummyBMP.getPixel32(x+xDisplace, y+yDisplace); } }; //TargetImage[x, y] := newcolor; //waterData.setPixel32(x, y, newcolor); //} } else { newcolor = dummyBMP.getPixel32(x,y); }; return newcolor; //return dummyBMP.getPixel32(10,10); //newcolor = Buffer2[col][row] << 24; //newcolor = newcolor + 0xff; //return newcolor; } public function dampEdgeOfWater(): void { var col:int; var row:int; //reduce the edge pixels for (col = 0; col < BufWidth; col++){ Buffer2[col][0] = Math.floor(Buffer2[col][0] >> damping); Buffer2[col][BufHeight - 1] = Math.floor(Buffer2[col][BufHeight - 1] >> damping); if (Buffer2[col][0] < 0) Buffer2[col][0] = 0; if (Buffer2[col][BufHeight - 1] < 0) Buffer2[col][BufHeight - 1] = 0; //SetColor HeightToPixel(col, 0); HeightToPixel(col, BufHeight - 1); } for (row = 0; row < BufHeight; row++) { Buffer2[0][row] = Math.floor(Buffer2[0][row] >> damping); Buffer2[BufWidth - 1][row] = Math.floor(Buffer2[BufWidth - 1][row] >> damping); if (Buffer2[0][row] < 0) Buffer2[0][row] = 0; if (Buffer2[BufWidth - 1][row] < 0) Buffer2[BufWidth - 1][row] = 0; //SetColor HeightToPixel(0, row); HeightToPixel(BufWidth - 1, row); } } //smooth outthe ripples public function updateRipple():void { var col:int; var row:int; var oldVal:int; var newVal:int; var smoothedVal:uint; //Now process the inner rectangle of water for (col = 1; col < BufWidth - 1; col++ ) { for (row = 1; row < BufHeight - 1; row++) { smoothedVal = Buffer1[col - 1][row] + Buffer1[col + 1][row] + Buffer1[col][row + 1] + Buffer1[col][row - 1] + Buffer1[col - 1][row - 1] + Buffer1[col - 1][row + 1] + Buffer1[col + 1][row - 1] + Buffer1[col + 1][row + 1]; newVal = Math.floor((((smoothedVal ) >> 2 ) - Buffer2[col][row])); newVal = newVal - ( newVal >> damping); if (newVal < 0) newVal = 0; //small optimisation if(Buffer2[col][row]!= newVal) { Buffer2[col][row] = newVal; HeightToPixel(col, row); } } } dampEdgeOfWater() } //update the arrays public function forceRefresh(): void { //Update the water waterData.lock(); updateRipple(); waterData.unlock(); //Swap buffer to retain direction and velocity tempBuff = Buffer2; Buffer2 = Buffer1; Buffer1 = tempBuff; } }
Join Effecthub.com
Working with Global Gaming Artists and Developers!
Login
Sign Up
Or Login with Your Email Address:
Email
Password
Remember
Or Sign Up with Your Email Address:
Your Email
This field must contain a valid email
Set Password
Password should be at least 1 character
Stay informed via email