Tarbell`s attractors 
    ATTRACTORS VERSION
BASED ON  
Happy Place
j.tarbell  March, 2004
Albuquerque, New Mexico
complexification.net
Processing 0085 Beta syntax update
j.tarbell   April, 2005 
    
    
    
       
       
       
       
      
         
       
     
    
    
   
  // forked from peko's Tarbell`s attractors
// forked from peko's forked from: forked from: forked from: BrownianMotion
// forked from nutsu's forked from: forked from: BrownianMotion
// forked from ton's forked from: BrownianMotion
// forked from ton's BrownianMotion
// ATTRACTORS VERSION
// BASED ON  
// Happy Place
// j.tarbell  March, 2004
// Albuquerque, New Mexico
// complexification.net
// Processing 0085 Beta syntax update
// j.tarbell   April, 2005
package {
    import flash.display.*;
    import flash.filters.*;
    import flash.events.*;
    import flash.geom.*;
    import frocessing.core.F5BitmapData2D;
    import net.hires.debug.Stats;
    
    [SWF(frameRate="60", backgroundColor="#FFFFFF")]
    public class BrownianMotion extends Sprite {
        private const N:int = 50;
        private const MAX_R:int = 200;
        private const W:int = 465;
        private const H:int = 465;
        private var fg:F5BitmapData2D;
        private var bmp:Bitmap;
        private var timeout:uint = 0;
        
        // original Tarbell`s palette
        private var p1:Array = [
            0x3a242b, 0x3b2426, 0x352325, 0x836454, 
            0x7d5533, 0x8b7352, 0xb1a181, 0xa4632e, 0xbb6b33, 0xb47249, 
            0xca7239, 0xd29057, 0xe0b87e, 0xd9b166, 0xf5eabe, 0xfcfadf, 
            0xd9d1b0, 0xfcfadf, 0xd1d1ca, 0xa7b1ac, 0x879a8c, 0x9186ad,
            0x776a8e, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 
            0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0x000000,
            0x000000, 0x000000, 0x000000, 0x000000, 0xFFFFFF, 0xFFFFFF,
            0xFFFFFF, 0xFFFFFF, 0xFFFFFF
        ];
        
        private var p2:Array = [0xFFFFFF, 0x565353, 0xBD3B00, 0xCD994F, 0xE3DACE, 0x2789B7];
        private var p3:Array = [0xFFFFFF, 0x721300, 0xCC0000, 0xCCAA00, 0xFFBB00, 0xFFFFB6];   
        private var p4:Array = [0xFFFFFF, 0x335533, 0x0055cc, 0x44ccdd, 0x99dddd, 0xcceeff];
        private var p5:Array = [0xFFFFFF, 0x191F13, 0x2F7A10, 0x006CFF, 0xFFE28E, 0xCDAB23];
        private var palettes:Array = [p1, p2, p3, p4, p5];        
        private var currentPalette:Array = palettes[Math.floor(Math.random()*palettes.length)];
        
        function BrownianMotion() {
            fg = new F5BitmapData2D(W, H, false, 0xFFFFFF);
            bmp = new Bitmap(fg.bitmapData);
            addChild(bmp);
            fg.strokeAlpha = 0.25;
            for (var i:int = 0; i < N; i++) {
                var d:Dot = new Dot(currentPalette[Math.floor(Math.random()*currentPalette.length)]);
                var angle:Number = Math.random() * (2 * Math.PI);
                d.x = Math.cos(angle) * MAX_R;
                d.y = Math.sin(angle) * MAX_R;
                d.x+=(Math.random()-Math.random())*50;
                d.y+=(Math.random()-Math.random())*50;
                d.vx = 0;
                d.vy = 0;
            }
            //addChild( new Stats() );
            addEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
        }
        private function onEnterFrameHandler(event:Event):void 
        {
            fg.beginDraw();
            fg.translate( W>>1, H>>1 );
            
            var boom:Boolean = (timeout++)>500;
            if (boom) {
             timeout = 0;
             currentPalette = palettes[Math.floor(Math.random()*palettes.length)];
              var bmd:BitmapData = fg.bitmapData;                  
              //bmd.applyFilter(bmd, bmd.rect, new Point(0,0), new BlurFilter());
              bmd.applyFilter(bmd, bmd.rect, new Point(), new ColorMatrixFilter([
                 1,    0,    0,    0,    128,
                 0,    1,    0,    0,    128,
                 0,    0,    1,    0,    128,
                 0,    0,    0,    1,    0
              ]));          
            }
            for each(var d:Dot in Dot.dots) {
                
                if (boom) {
                var angle:Number = Math.random() * (2 * Math.PI);
                    d.x = Math.cos(angle) * MAX_R;
                    d.y = Math.sin(angle) * MAX_R;
                    d.x+=(Math.random()-Math.random())*50;
                    d.y+=(Math.random()-Math.random())*50;
                    d.color = currentPalette[Math.floor(Math.random()*currentPalette.length)]
                }
                d.update();
                
                var t:Dot = Dot.dots[d.targetID]; 
                var pp:uint = Math.abs(t.x-d.x)/(1+Math.random()*2);
                
                fg.strokeColor = d.color
                for (var i:uint =0; i<=pp; i++){
                    var px:int = d.x + (t.x-d.x)*(pp-i)/pp;
                    var py:int = d.y + (t.y-d.y)*(pp-i)/pp;
                    fg.strokeAlpha = 0.25*(pp-i)/pp;
                    fg.pixel( px, py );
                }
            }
            fg.endDraw();
        }
    }
}
class Dot{
    public var vx:Number;
    public var vy:Number;
    public var x:Number;
    public var y:Number;
    public var color:uint;
    
    private const X:Number = 1;
    private const F:Number = 0.85;
    
    public static var dots:Array = []; 
    public var targetID:int;
    function Dot(color:uint) {
        this.color = color;
        targetID = Math.floor(Math.random()*dots.length);
        dots.push(this);
    }
    public function update():void {
        
        if(Math.random()>0.995) targetID = Math.floor(Math.random()*dots.length);
        
        vx -= (x - dots[targetID].x)/500;
        vy -= (y - dots[targetID].y)/500;
         
        vx *= F;
        vy *= F;
        x += vx;
        y += vy;
    }
    
}