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
// 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
//
// write as3 code here..
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;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
removeEventListener(Event.ADDED_TO_STAGE, init);
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, 10);
}
private function MouseClicky(event:MouseEvent):void {
Water.setDrop(event.localX, event.localY);
};
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 TestScale:Number = 5.0;
private const BufWidth:uint = 93;
private const BufHeight:uint = 93;
private const MaxHeight:uint = 256;
private const damping:Number = 64;
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;
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 hoold 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;
}
}
}
//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;
pixelColor = Buffer2[col][row] << 24;
pixelColor = pixelColor + 0xff;
waterData.setPixel32(col + 1, row + 1, pixelColor)
}
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;
//Now process the inner rectangle of water
for (col = 1; col < BufWidth - 1; col++ ) {
for (row = 1; row < BufHeight - 1; row++) {
var oldVal:int = Buffer2[col][row];
var newVal:int = Math.floor((((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] ) / 4) - oldVal));
newVal = newVal - ( newVal / damping);
if (newVal < 0) newVal = 0;
//small optimisation
if(oldVal != 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;
}
}