/** * @Revision * -Hold mouse down to apply attracting force * @author Mario Gonzalez * @see http://onedayitwillmake.com/ */ package { import flash.display.GradientType; import flash.display.Graphics; import flash.display.Shape; import flash.display.SpreadMethod; import flash.display.Sprite; import flash.display.StageQuality; import flash.events.Event; import flash.events.MouseEvent; import flash.geom.Matrix; import flash.display.BitmapData; import flash.display.PixelSnapping import flash.display.Bitmap; import flash.filters.ColorMatrixFilter; import flash.geom.ColorTransform; import flash.geom.Matrix; [SWF(width="465", height="465", background="#000000")] public class Proximity extends Sprite { //Parameters private var _cCount :int = 0; private var _cMax :int = 80; //Rendering private var _canvas :Sprite; public var _canvasGraphics :Graphics //Reference public var _lastCircle :Circle; //Movement public var _mousePressed :Boolean = false; public function Proximity() { stage.quality = StageQuality.LOW addChildAt(createBG(), 0); addChild(_canvas = new Sprite()); _canvasGraphics = _canvas.graphics; create(); addEventListener(Event.ENTER_FRAME, loop); stage.addEventListener(MouseEvent.MOUSE_DOWN, toggleMouseDown); stage.addEventListener(MouseEvent.MOUSE_UP, toggleMouseDown); } private function createBG():Sprite { trace(Wonderfl) var matr:Matrix = new Matrix(); matr.createGradientBox(465, 465, Math.PI / 2, 0, 0); var bg:Sprite = new Sprite(); bg.graphics.beginGradientFill ( GradientType.LINEAR, [0x000021, 0x000000], //colors [1, 1], //alphas [0, 255], //ratios matr, //matrix SpreadMethod.PAD ); bg.graphics.drawRect(0, 0, 465, 465); bg.graphics.endFill(); return bg; } /** * Main program loop */ private function loop(e:Event):void { draw(); } /** * Creates more circles if we have not reached the maximum count */ public function create():void { if(_cCount >= _cMax) return; var c:Circle; for(var i:int = 0; i < _cMax; i++) { c =new Circle(this); c.x = c._ix = Math.random() * (stage.stageWidth - 26) + 13; c.y = c._iy = Math.random() * (stage.stageHeight - 26) + 13; _canvas.addChild(c); _cCount++; if(_lastCircle) c._prev = _lastCircle; _lastCircle = c; } } /** * Draws the proximity field between the circles */ public function draw():void { _canvas.graphics.clear(); _canvas.graphics.lineStyle(0.5, 0xfffffff, 0.3); if(_lastCircle == null) return; _lastCircle.checkForProximity(_lastCircle._prev); _lastCircle.move(); } public function toggleMouseDown(e:MouseEvent):void { if(_mousePressed) _mousePressed = false; else _mousePressed = true; } } } import flash.display.Shape; import flash.display.BlendMode import flash.display.Sprite; /** * Circles that live in the feild */ class Circle extends Sprite { private var _radius :Number = Math.random() * 5 + 5; private var _curveModifier :Number = Math.random() * 50 - 25; public var _p :Proximity; //reference public var _prev :Circle; //Linked list style behavior //MOVEMENT public static var ACC_PARAM:Number = 0.1; public static var VELOCITY_PARAM:Number = 0.8 public var _ix:Number; public var _iy:Number; public var _vx:Number = 0.1; public var _vy:Number = 0; public var _ax:Number = 0; public var _ay:Number = 0; /** * Individual Circles know only the Circle created previously to their own */ public function Circle(p:Proximity):void { _p = p; blendMode = BlendMode.ADD graphics.beginFill(Math.random() * 255 * 255 * 255, 0.5) graphics.drawCircle(0, 0, _radius); graphics.endFill(); /* graphics.beginFill(Math.random() * 255 | 255 << 255) graphics.drawCircle(0, 0, 4); graphics.endFill(); */ } /** * Check all previous circles for proximity, and do [something] * There is no need for each circle to check the ones ahead, * because they've already checked against this one. * * Called recursively for this circle, until the linked list reaches the first circle. * Once it does, it calls checkForProximity on its '_prev' * The sequence repeats until there are no more previous ones * * @param tc:Circle The 'test circle' we will check against. */ public function checkForProximity(tc:Circle):void { if(tc == null) return; // This is the first circle created (unless error of course!) var d:Number = Math.sqrt((x - tc.x) * (x - tc.x) + (y - tc.y) * (y - tc.y)); if(d < 90) { _p._canvasGraphics.moveTo(x, y); //_p._canvasGraphics.lineTo(tc.x, tc.y); //_p._canvasGraphics.curveTo(tc.x, tc.y); _p._canvasGraphics.curveTo((x + tc.x) * 0.5, (y + tc.y) * 0.5 + _curveModifier, tc.x, tc.y); } //Keep checking backwards for proximity, until you reach the first circle if(tc._prev) checkForProximity(tc._prev); else if(_prev) //Reached first circle. We are the last created circle, so continue the loop until we reach the first _prev.checkForProximity(_prev._prev); } /** * Moves the circle, initial position relative to mouse attraction/repelling force */ public function move():void { //Don't let the force become too strong, by saying the distance will always be X at min var dist:Number = Math.max(Math.sqrt((x - stage.mouseX) * (x - stage.mouseX) + (y - stage.mouseY) * (y - stage.mouseY)), 40); var dy:Number = stage.mouseY - y; var dx:Number = stage.mouseX - x var angle:Number = Math.atan2(dy, dx); var f:Number = 1 / dist * 400 * ((_p._mousePressed == true) ? 1 : -1); _ax += Math.cos(angle) * f; _ay += Math.sin(angle) * f; _ax += (_ix - x) * ACC_PARAM; _ay += (_iy - y) * ACC_PARAM; _vx = (_vx + _ax) * VELOCITY_PARAM; _vy = (_vy + _ay) * VELOCITY_PARAM; x += _vx; y += _vy; _ax = _ay = 0; if(_prev) //Call move on all circles _prev.move(); } public function destroy():void { // _p._firstCircle = this; } } forked from: study090531