In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

forked from: INK BLEED

<p>Ink Bleed</p>
@author monoDreamer, aka ryo
@langversion ActionScript 3.0
@playerversion Flash 10.2+
@see
Get Adobe Flash player
by aobyrne 18 Apr 2012
/**
 * Copyright aobyrne ( http://wonderfl.net/user/aobyrne )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/1I9U
 */

package
{
    import com.greensock.easing.Elastic;
    import com.greensock.easing.Expo;
    import com.greensock.TweenLite;
    import flash.display.Graphics;
    import net.hires.debug.Stats;
    
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.events.TimerEvent;
    import flash.filters.DisplacementMapFilter;
    import flash.filters.DisplacementMapFilterMode;
    import flash.geom.ColorTransform;
    import flash.geom.Point;
    import flash.utils.Timer;
    
    [SWF(width=465, height=465, frameRate=30)]
    
    /**
     * <p>Ink Bleed</p>
     * @author monoDreamer, aka ryo
     * @langversion ActionScript 3.0
     * @playerversion Flash 10.2+
     * @see 
     */
    public class InkBleed extends Sprite
    {
        //----------------------------------------------------------------
        // Properties
        //----------------------------------------------------------------
        
        //----------------------------------------------------------------
        // Getter/Setter Method
        //----------------------------------------------------------------
        
        //----------------------------------------------------------------
        // Public method
        //----------------------------------------------------------------
        
        //----------------------------------------------------------------
        // Protected Method
        //----------------------------------------------------------------
        protected function timerHandler($e:TimerEvent):void
        {
            var i:int = _pnum;
            while (--i>-1) {
                _dots[i].diffuse();
            }
        }
        
        protected function render($e:Event):void
        {
            var d:Dot, i:int, c:uint;
            if (_isMouseDown) {
                i = _px + _py*_cw;
                _dots[i].cur += 0x2f0;
            }
            
            i = _pnum;
            while (--i>-1) {
                    c = _dots[i].cur;
                    _canvasData[i] = (c > 0xff ? 0xff : c) << 24;
            }
            _canvas.setVector(_canvas.rect, _canvasData);
        }
        
        protected function downHandler($e:MouseEvent):void
        {
            var mx:int = stage.mouseX >> DX, my:int = stage.mouseY >> DY;
            
            if (_canvas.rect.contains(mx, my)) {
                _px = mx;
                _py = my;
                _isMouseDown = true;
                stage.addEventListener(MouseEvent.MOUSE_MOVE, moveHandler);
            }
        }
        
        protected function moveHandler($e:MouseEvent):void
        {
            trace( "----------------------------- " );
            if(_isMouseDown) {
                var mx:int = stage.mouseX >> DX;
                var my:int = stage.mouseY >> DY;
                mx = uint(leader.x) >> DX;
                trace( "leader.x : " + leader.x );
                trace( "mx : " + mx );
                my = uint(leader.y) >> DY;
                trace( "leader.y : " + leader.y );
                trace( "my : " + my );
                if (_canvas.rect.contains(mx, my))
                {
                    t_efla(_px, _py, mx, my, 0x1ff);
                    _px = mx;
                    _py = my;
                }
            }
        }
        
        protected function upHandler($e:MouseEvent):void
        {
            _isMouseDown = false;
            stage.removeEventListener(MouseEvent.MOUSE_MOVE, moveHandler);
        }
        
        protected function t_efla($sx:int, $sy:int, $ex:int, $ey:int, $color:uint):void
        {
            var shortLen:int = $ey - $sy;
            var longLen:int = $ex - $sx;
            if (!longLen) if (!shortLen) return;
            var i:int, id:int, inc:int;
            var multDiff:Number;
            var idx:int;
            
            // TODO: check for this above, swap x/y/len and optimize loops to ++ and -- (operators twice as fast, still only 2 loops)
            if ((shortLen ^ (shortLen >> 31)) - (shortLen >> 31) > (longLen ^ (longLen >> 31)) - (longLen >> 31)) {
                if (shortLen < 0) {
                    inc = -1;
                    id = -shortLen & 3;
                } else {
                    inc = 1;
                    id = shortLen & 3;
                }
                multDiff = !shortLen ? longLen : longLen / shortLen;
                if (id) {
                    idx = $sx + $sy*_cw;
                    _dots[idx].cur += $color;
                    
                    i += inc;
                    if (--id) {
                        idx = roundPlus($sx + i * multDiff) + ($sy + i)*_cw;
                        _dots[idx].cur += $color;
                        i += inc;
                        if (--id) {
                            idx = roundPlus($sx + i * multDiff) + ($sy + i)*_cw;
                            _dots[idx].cur += $color;
                            i += inc;
                        }
                    }
                }
                
                while (i != shortLen) {
                    idx = roundPlus($sx + i * multDiff) + ($sy + i) * _cw;
                    _dots[idx].cur += $color;
                    i += inc;
                    idx = roundPlus($sx + i * multDiff) + ($sy + i) * _cw;
                    _dots[idx].cur += $color;
                    i += inc;
                    idx = roundPlus($sx + i * multDiff) + ($sy + i) * _cw;
                    _dots[idx].cur += $color;
                    i += inc;
                    idx = roundPlus($sx + i * multDiff) + ($sy + i) * _cw;
                    _dots[idx].cur += $color;
                    i += inc;
                }
            } 
            else {
                if (longLen < 0) {
                    inc = -1;
                    id = -longLen & 3;
                } else {
                    inc = 1;
                    id = longLen & 3;
                }
                multDiff = !longLen ? shortLen : shortLen / longLen;
                
                if (id) {
                    idx = $sx + $sy * _cw;
                    _dots[idx].cur += $color;
                    i += inc;
                    if (--id) {
                        idx = $sx + i + roundPlus($sy + i * multDiff) * _cw;
                        _dots[idx].cur += $color;
                        i += inc;
                        if (--id) {
                            idx = $sx + i + roundPlus($sy + i * multDiff) * _cw;
                            _dots[idx].cur += $color;
                            i += inc;
                        }
                    }
                }
                
                while (i != longLen) {
                    idx = $sx + i + roundPlus($sy + i * multDiff) * _cw;
                    _dots[idx].cur += $color;
                    i += inc;
                    idx = $sx + i + roundPlus($sy + i * multDiff) * _cw;
                    _dots[idx].cur += $color;
                    i += inc;
                    idx = $sx + i + roundPlus($sy + i * multDiff) * _cw;
                    _dots[idx].cur += $color;
                    i += inc;
                    idx = $sx + i + roundPlus($sy + i * multDiff) * _cw;
                    _dots[idx].cur += $color;
                    
                    i += inc;
                }
                
            }
        }
        
        protected function roundPlus($value:Number):int {
            return ($value + BIG_ENOUGH_ROUND) - BIG_ENOUGH_INT;
        }
        
        //----------------------------------------------------------------
        // Private Method
        //----------------------------------------------------------------
        /** Constructor */
        public function InkBleed():void
        {
            super();
            
            _cw = 200
            _ch = 200;
            _pnum = _cw * _ch;
            leader = addChild(new Sprite) as Sprite;
            var g:Graphics = leader.graphics;
            g.lineStyle(0);
            g.drawRect( -3, 3, 6, 6);
            functions = Vector.<Function>([]);
            functions[functions.length] = Elastic.easeIn;
            functions[functions.length] = Elastic.easeInOut;
            functions[functions.length] = Elastic.easeOut;
            functions[functions.length] = Expo.easeIn;
            functions[functions.length] = Expo.easeOut;
            functions[functions.length] = Expo.easeInOut;
            leader.x = 50;
            _px = leader.x >> DX;
            TweenLite.to(leader, 5, {  y:300, onComplete:oc});
            init();
            addEventListener(Event.ENTER_FRAME, ef);
            _isMouseDown = true;
        }
        
        private function ef(e:Event):void 
        {
            moveHandler(null);
        }
        
        private function oc():void 
        {
            trace('....................................');
            _isMouseDown = false;
            removeEventListener(Event.ENTER_FRAME, ef);
            if (functionIndex<functions.length) 
            {
                var currentFunction:Function = functions[functionIndex];
                leader.x += 50;
                _px = leader.x >> DX;
                leader.y = 0;
                _py = leader.y >> DY;
                TweenLite.to(leader, 5, { y:300, ease:currentFunction, onComplete:oc } );
                _isMouseDown = true;
                addEventListener(Event.ENTER_FRAME, ef);
            }
            functionIndex++;
            
        }
        
        /** Initialize */
        private function init():void
        {
            initTimer();
            initDots();
            initCanvas();
            addListeners();
            
            _timer.start();
        }
        
        private function initTimer():void
        {
            _timer = new Timer(100);
            _timer.addEventListener(TimerEvent.TIMER, timerHandler);
        }
        
        private function initCanvas():void
        {
            _canvas = new BitmapData(_cw, _ch, true, 0);
            _canvasData = _canvas.getVector(_canvas.rect);
            _canvasData.fixed = true;
            
            var map:BitmapData = new BitmapData(_cw * SCX, _ch *SCY);
            map.perlinNoise(map.width * .4, map.height * .4, 8, Math.random()*100, true, true, 1, true);
            
            var bmp:Bitmap = new Bitmap(_canvas);
                bmp.smoothing = true;
                bmp.scaleX = SCX;
                bmp.scaleY = SCY;
                bmp.filters = [new DisplacementMapFilter(map, new Point(), 1, 1, 32, 32, DisplacementMapFilterMode.CLAMP)];
            addChild(bmp);
            
            graphics.lineStyle(1);
            graphics.drawRect(0, 0, _cw * SCX, _ch * SCY);
            
            var stat:Stats = new Stats();
                stat.x = 400;
            addChild(stat);
        }
        
        private function addListeners():void
        {
            addEventListener(Event.ENTER_FRAME, render);
            //stage.addEventListener(MouseEvent.MOUSE_DOWN, downHandler);
            //stage.addEventListener(MouseEvent.MOUSE_UP, upHandler);
        }
        
        private function initDots():void
        {
            var absorbMap:BitmapData = new BitmapData(_cw, _ch, false, 0);
                absorbMap.perlinNoise(_cw/2, _ch/2, 5, 100*Math.random(), true, true, 1, true);
                absorbMap.colorTransform(absorbMap.rect, new ColorTransform(.2, .2, .2));
            var maxCapMap:BitmapData = new BitmapData(_cw, _ch, false, 0xffffff);
                maxCapMap.perlinNoise(_cw, _ch, 5, 100 * Math.random(), true, true, 1, true);
                maxCapMap.colorTransform(maxCapMap.rect, new ColorTransform(1.8, 1.8, 1.8));
            var d:Dot, i:int = _pnum;
            
            _dots = new Vector.<Dot>(_pnum, true);
            while(--i>-1) {
                _dots[i] = new Dot();
            }
            
            var neighbors:Array;
            for (var my:int=0; my<_ch; my++)
            {
                for (var mx:int=0; mx<_cw; mx++)
                {
                    i = mx + my*_cw;
                    d = _dots[i];
                    neighbors = [];
                    d.abs = absorbMap.getPixel(mx, my) & 0xff;
                    d.max = maxCapMap.getPixel(mx, my) & 0xff;
                    
                    if (mx>0) neighbors.push(_dots[i-1]);
                    if (mx<_cw-1) neighbors.push(_dots[i+1]);
                    if (my>0) neighbors.push(_dots[i-_cw]);
                    if (my<_ch-1) neighbors.push(_dots[i+_cw]);
                    
                    d.setNeighbors(neighbors);
                }
            }
        }
        
        private const BIG_ENOUGH_INT:int = 16 * 1024;
        private const BIG_ENOUGH_ROUND:Number = BIG_ENOUGH_INT + 0.5;
        private const SCX:int = 2;
        private const SCY:int = 2;
        private var DX:int = 1;
        private var DY:int = 1;
        
        private var _canvasData:Vector.<uint>;
        private var _canvas:BitmapData;
        private var _pnum:int;
        private var _dots:Vector.<Dot>;
        private var _cw:int;
        private var _ch:int;
        private var _px:int;
        private var _py:int;
        private var _isMouseDown:Boolean;
        private var _timer:Timer;
        private var leader:Sprite;
        private var functions:Vector.<Function>;
        private var functionIndex:uint;
    }
}

class Dot
{
    public var max:uint;
    public var cur:uint;
    public var abs:uint;
    public var isOver:Boolean;
    
    public function setNeighbors($neighbors:Array):void
    {
        _neighbors = Vector.<Dot>($neighbors);
        _neighbors.fixed = true;
        _len = _neighbors.length;
    }
    
    public function diffuse():void
    {
        if (cur <= max) return;
        isOver = true;
        var d:Dot, l:int = _len;
        while (--l > -1) {
            d = _neighbors[l];
            if (d.isOver|| cur<d.abs) continue;
            d.cur += d.abs;
        }
        cur -= d.abs * .2;
    }
    
    private var _neighbors:Vector.<Dot>;
    private var _len:int;
}