package { import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.BitmapDataChannel; import flash.display.BlendMode; import flash.display.Sprite; import flash.events.Event; import flash.filters.BlurFilter; import flash.geom.ColorTransform; import flash.geom.Matrix; import flash.geom.Point; import flash.geom.Rectangle; [SWF(width="465", height="465", backgroundColor="#FFFFFF", frameRate="30")] public class Water extends Sprite { private var canvas:BitmapData; private var screen:BitmapData; private var screen2:BitmapData; private var container:Sprite = new Sprite(); private var roof:Sprite = new Sprite(); private var pool:Pool = new Pool( -100, 465 + 200, 465 - 50, 465 + 50); private var _blur:BlurFilter = new BlurFilter(32, 32); private var _rect:Rectangle; private var _pt:Point = new Point(); private var _drops:Vector.<Drop> = new Vector.<Drop>(); public function Water() { var s:Bitmap; addChild(new Bitmap(canvas = new BitmapData(465, 465, true, 0xFFFFFFFF))); addChild(s = new Bitmap(screen2 = new BitmapData(465, 465, true, 0x00000000))); screen = screen2.clone(); s.blendMode = BlendMode.SCREEN; _rect = canvas.rect; container.addChild(roof); container.addChild(pool); addEventListener("enterFrame", loop); roof.graphics.beginFill(0); roof.graphics.drawRect(-100, -50, 465+200, 70); roof.graphics.endFill(); var b:int = 16; container.filters = [new BlurFilter(b,b,1)]; } private function loop(event:Event):void { if (Math.random() < 0.08) { container.addChild(_drops[_drops.length] = new Drop(pool)); } var n:uint = _drops.length; for (var i:uint = 0; i < n; i++) { var drop:Drop = _drops[i]; if (drop.update()) { var s:Number = drop.scaleX; var matrix:Matrix = new Matrix(s, 0, 0, s, drop.x, drop.y); //drop.filters = [new BlurFilter(32,32)]; screen.draw(drop, matrix); container.removeChild(drop); _drops.splice(i, 1); i--; n--; } } pool.update(); canvas.fillRect(_rect, 0x00FFFFFF); canvas.draw(container); canvas.threshold(canvas, _rect, _pt, "<", 0x80FFFFFF, 0xFFFFFFFF, 0xFF000000, true); screen.applyFilter(screen, _rect, _pt, _blur); screen.draw(screen, null, null, BlendMode.ERASE); screen2.draw(screen); screen2.applyFilter(screen2, _rect, _pt, _blur); } } } import flash.display.Sprite; class Drop extends Sprite { private var _pool:Pool; private var ay:Number = 0; private var size:Number = 0; public var color:uint = 0x000000; public function Drop(pool:Pool) { _pool = pool; this.x = Math.random() * 465 >> 0; this.y = 15; size = Math.random() * 20 + 20; color = hsl(Math.random()*360, 0.85, 0.6); graphics.beginFill(color); graphics.drawCircle(0,0,5); graphics.endFill(); scaleX = scaleY = Math.random(); } public function update():Boolean { if (width < size) { scaleX += scaleX * 0.45; scaleY = scaleX; } else { ay += 0.65; y += ay; if (y > _pool.top) { _pool.hit(x, y + ay); return true; } } return false; } } class Pool extends Sprite { private var points:Vector.<Particle> = new Vector.<Particle>(); public var left:int = 0; public var right:int = 0; public var top:int = 0; public var bottom:int = 0; public function Pool(left:int, right:int, top:int, bottom:int) { this.left = left; this.right = right; this.top = top; this.bottom = bottom; var w:int = right - left; var n:uint = 30; for (var i:uint = 0; i < n; i++) { points[i] = new Particle(w / n * (i + 1) + left, top); } update(); } public function hit(x:Number, y:Number):void { var w:int = right - left; var n:uint = points.length; var i:uint = (x - left) / (w / n) >> 0; points[i].move(points[i].x, points[i].y + y); } public function update():void { graphics.clear(); graphics.beginFill(0x000000); graphics.moveTo(right, top); graphics.lineTo(right, bottom); graphics.lineTo(left, bottom); graphics.lineTo(left, top); var n:uint = points.length; var nx:Number = 0; var ny:Number = 0; for (var i:uint = 0; i < n; i++) { nx = points[i].x; if (i>1 && i < n-1) { ny = (points[i - 1].y + points[i + 1].y) * .5; } else { ny = points[i].vy; } points[i].move(nx, ny); points[i].update(); } for (i = 0; i < n; i++) { var p:Particle = points[i]; graphics.lineTo(p.x, p.y); } graphics.endFill(); } } class Particle { private var tx : Number = 0; private var ty : Number = 0; private var ox : Number = 0; private var oy : Number = 0; public var vx : Number = 0; public var vy : Number = 0; public var x : Number = 0; public var y : Number = 0; public function Particle(x:Number, y:Number) { this.tx = this.vx = this.ox = this.x = x; this.ty = this.vy = this.oy = this.y = y; } public function move(tx:Number, ty:Number):void { this.tx = (this.tx + tx) * .5; this.ty = (this.ty + ty) * .5; } public function update():void { var nx:Number = (x - ox) * 0.85; ox = x; x += (tx - x) * 0.45 + nx; var ny:Number = (y - oy) * 0.85; oy = y; y += (ty - y) * 0.45 + ny; tx += (vx - tx) * 0.45; ty += (vy - ty) * 0.45; } } function hsl (h:Number, s:Number, l:Number, a:Number = 0.0):uint { var r:Number = 0, g:Number = 0, b:Number = 0, cmin:Number, cmax:Number; if (s < 0) s = 0; if (s > 1) s = 1; if (l < 0) l = 0; if (l > 1) l = 1; h = h % 360; if (h < 0) h = h + 360; if (l <= 0.5) { cmin = l * ( 1 - s ); cmax = 2 * l - cmin; } else { cmax = l * ( 1 - s ) + s; cmin = 2 * l - cmax; }; r = _h2v(h + 120, cmin, cmax) * 0xFF; g = _h2v(h, cmin, cmax) * 0xFF; b = _h2v(h - 120, cmin, cmax) * 0xFF; a *= 0xFF; return a << 24 | r << 16 | g << 8 | b << 0; } function _h2v (h:Number, min:Number, max:Number):Number { h = h % 360; if (h < 0) h = h + 360; if (h < 60) return min + (max - min) * h / 60; if (h >= 60 && h < 180) return max; if (h >= 180 && h < 240) return min + (max - min) * (240 - h) / 60; return min; } code on 2008-12-24