package ae { import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; class Circle extends Sprite { //width public var w:Number; //height public var h:Number; //radius public var r:Number; //radius / 2 public var r2:Number; //color public var c:int; // interpolation factor private var t:Number = 0; // time step private var step:Number = 0.06; public var node:CircleNode; public static var cs:CircleSplit; public function Circle(_w:Number, _h:Number, _cs:CircleSplit = null) { super(); w = _w; h = _h; r = w/2; r2 = r/2; if (_cs != null) Circle.cs = _cs; } public function setColor() : void { if (Circle.cs.pic == null) { //generate a random color that's not too dark var red:int = int(Math.random() * 224) + 32; var g:int = int(Math.random() * 224) + 32; var b:int = int(Math.random() * 224) + 32; c = (red << 16) + (g << 8) + b; return; } //sample the pic var xm:int = x+r; var ym:int = y+r; var c1:int = Circle.cs.pic.getPixel32(int(xm-r2), int(ym-r2)); var c2:int = Circle.cs.pic.getPixel32(int(xm+r2), int(ym-r2)); var c3:int = Circle.cs.pic.getPixel32(int(xm-r2), int(ym+r2)); var c4:int = Circle.cs.pic.getPixel32(int(xm+r2), int(ym+r2)); var cm:int = Circle.cs.pic.getPixel32(int(xm), int(ym)); c = averageColor(new Array(c1, c2, c3, c4, cm, cm) ); } private function averageColor(a:Array):int { var rt:int = 0; var gt:int = 0; var bt:int = 0; for each(var cc:int in a) { rt += (cc >> 16) & 0xFF; gt += (cc >> 8) & 0xFF; bt += (cc >> 0) & 0xFF; } return ((rt/a.length) << 16) + ((gt/a.length) << 8) + (bt/a.length); } private function handleFrame(e:Event) { if (t >= 1) { // we're done animating removeEventListener(Event.ENTER_FRAME, handleFrame); split(); } else { t += step; draw(); } } // draw 4 circles (while animating) // animate by interpolating the x,y coords and radius public function draw():void { this.graphics.clear(); // blank the bg behind the original circle // this happens after the first step to avoid a flicker if (t == step) (this.parent as CircleSplit).drawSquare(this); this.graphics.beginFill(c); this.graphics.drawCircle(lerp(r, r-r2, t) , lerp(r, r-r2, t), lerp(r, r2, t)); this.graphics.endFill(); this.graphics.beginFill(c); this.graphics.drawCircle(lerp(r, r-r2, t) , lerp(r, r+r2, t), lerp(r, r2, t)); this.graphics.endFill(); this.graphics.beginFill(c); this.graphics.drawCircle(lerp(r, r+r2, t) , lerp(r, r-r2, t), lerp(r, r2, t)); this.graphics.endFill(); this.graphics.beginFill(c); this.graphics.drawCircle(lerp(r, r+r2, t) , lerp(r, r+r2, t), lerp(r, r2, t)); this.graphics.endFill(); } public function handleMouseOver(e:MouseEvent) { // dont split if the mouse button is down if(e.buttonDown) return; // if we're already animating, don't do anything if(t > 0) return; // still have to do a hitTest if ( !hitTest(e) ) return; // start recieveving frame events to animate addEventListener(Event.ENTER_FRAME, handleFrame); this.graphics.clear(); } // check to see if the mouse is actually inside the circle; private function hitTest(e:MouseEvent) : Boolean { var dx:Number = Math.abs(x+r - e.stageX); var dy:Number = Math.abs(y+r - e.stageY); var dist = Math.sqrt(dx*dx +dy*dy); return dist <= r; } // split into 4 sub-circles/nodes public function split():void { //create the 4 child Circles var c1:Circle = new Circle(r, r); var c2:Circle = new Circle(r, r); var c3:Circle = new Circle(r, r); var c4:Circle = new Circle(r, r); // the global midlines of the circle var ymid:Number = y+r; var xmid:Number = x+r; // set up their coords c1.x = x; c1.y = y; c2.x = xmid; c2.y = y; c3.x = x; c3.y = ymid; c4.x = xmid; c4.y = ymid; c1.setColor(); c2.setColor(); c3.setColor(); c4.setColor(); // create the assicated tree nodes var cn1:CircleNode = new CircleNode(c1); var cn2:CircleNode = new CircleNode(c2); var cn3:CircleNode = new CircleNode(c3); var cn4:CircleNode = new CircleNode(c4); // set the thresholds on the nodes cn1.xThresh = xmid - r2; cn1.yThresh = ymid - r2; cn2.xThresh = xmid + r2; cn2.yThresh = ymid - r2; cn3.xThresh = xmid - r2; cn3.yThresh = ymid + r2; cn4.xThresh = xmid + r2; cn4.yThresh = ymid + r2; // set up the tree node.addChildren(cn1, cn2, cn3, cn4); // draw the new circles (this.parent as CircleSplit).addCircles(new Array(c1, c2, c3, c4)); // this circle is no longer needed, remove all references to it node.parentCircle = null; node = null; this.parent.removeChild(this); } // standard linear interpolation function private function lerp(a:Number, b:Number, t:Number) : Number { return a * (1-t) + b * t; } } }