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: forked from: bitmapData를 이용한 태풍

/**
 * Copyright p100bell ( http://wonderfl.net/user/p100bell )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/nPh4
 */

// forked from p100bell's forked from: bitmapData를 이용한 태풍
// forked from jidolstar's bitmapData를 이용한 태풍
// forked from uwi's forked from: forked from: 渦巻
// forked from yd_niku's forked from: 渦巻
// forked from okoi's 渦巻
//
//    渦、台風っぽく
//    高速化しないと重いな
//    ブラーもかけたいかも
//    じっと見てると目をまわします
//
package {
    import flash.accessibility.Accessibility;
    import flash.display.*;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.filters.BlurFilter;
    import flash.geom.*;

    import net.hires.debug.*;

    [SWF(frameRate=60)]
    /**
     * 태풍 효과
     * @author okoi
     * @see http://wonderfl.net/code/d15a9c65440eaba3fb852462f61a521554282d74
     */
    public class bitmap_typhoon extends Sprite {
        private static const POWDER_NUM:int=3000;
        private var _spire:Spire;
        private var _container:Bitmap;
        private var _firstPowder:Powder;
        private var _canvas:BitmapData;
        private var _filters:Array = [new BlurFilter(2, 2)]; //Blur 효과 
        private var _gain:ColorTransform = new ColorTransform(0.97, 0.97, 0.99, 1); //꼬리를 가지며 따라오는 효과. blue값이 더 큰것은 녹색 빛깔을 가지도록 하기 위해 

        public function bitmap_typhoon():void {
            if (stage)
                INIT();
            else
                addEventListener(Event.ADDED_TO_STAGE, INIT);
        }

        private function INIT(e:Event=null):void {
            removeEventListener(Event.ADDED_TO_STAGE, INIT);

            stage.scaleMode=StageScaleMode.NO_SCALE;
            stage.align=StageAlign.TOP_LEFT;

            // entry point
            _spire=new Spire();
            
            //태풍 효과를 출력할 영역 
            _container=new Bitmap();
            _container.scaleX=_container.scaleY=2; //1px은 감질맛 나니깐 더 크게~ ^^
            addChild(_container);

            //메모리/frameRate 상태 표시 
            addChild(new Stats());

            //cf)http://blog.jidolstar.com/656
            if (stage.stageWidth > 0 && stage.stageHeight > 0) {
                setup();
                addEventHandler();
            } else {
                addEventListener(Event.ENTER_FRAME, function($e:Event):void {
                        if (stage.stageWidth > 0 && stage.stageHeight > 0) {
                            $e.target.removeEventListener($e.type, arguments.callee);
                            setup();
                            addEventHandler();
                        }
                    });
            }
        }
        
        private function addEventHandler():void {
            stage.addEventListener(Event.RESIZE, RESIZE);
            addEventListener(Event.ENTER_FRAME, ENTER_FRAME);
            stage.addEventListener(MouseEvent.MOUSE_DOWN, MOUSE_DOWN);
            stage.addEventListener(MouseEvent.MOUSE_UP, MOUSE_UP);
        }

        private function setup():void {
            _firstPowder=null;

            var powder:Powder, pre:Powder;
            var sw:Number=stage.stageWidth;
            var sh:Number=stage.stageHeight;
            
            //Powder 생성 및 최초 위치 지정 
            for (var i:int=0; i < POWDER_NUM; i++) {
                var x:Number=Math.random() * sw;
                var y:Number=Math.random() * sh;
                powder=new Powder(x, y, int(Math.random() * 1000)); 
                if (!_firstPowder) { //최초 Powder 
                    _firstPowder=powder;
                }
                if (pre) { //링크드 리스트 연결
                    pre.next=powder;  
                }
                pre=powder;
            }
            //비트맵 데이타 초기화 
            if (_canvas) {
                _canvas.dispose();
                _canvas=null;
            }
            _canvas=new BitmapData(sw >> 1, sh >> 1, false, 0);
            _container.bitmapData=_canvas;
        }

        private function MOUSE_DOWN($e:MouseEvent):void {
            Powder.speed=6;
        }

        private function MOUSE_UP($e:MouseEvent):void {
            Powder.speed=1;
        }

        private function ENTER_FRAME(e:Event):void {
            _spire.Update(stage.mouseX, stage.mouseY); //마우스 위치로 태풍의 중심 설정 

            //모든 Powder를 Spire에 지정된 위치를 중심으로 회전 이동 
            var powder:Powder=_firstPowder; //powders[0];
            do {
                powder.Move(_spire);
            } while ((powder=powder.next) != null);

            powder=_firstPowder; //powders[0];

            var r:uint, g:uint, b:uint, c:uint;
            var p:Point=new Point(), o:Point=p.clone();

            _canvas.lock(); 
            //_canvas.fillRect( _canvas.rect, 0x00 );
            _canvas.colorTransform(_canvas.rect, _gain); //꼬리치며 따라오게~~ ^^
            //canvas에 powder를 rendering한다.
            do {
                p.x=powder.posX >> 1;
                p.y=powder.posY >> 1;
                _canvas.setPixel(p.x, p.y, 0xffffff);
            } while ((powder=powder.next) != null);
            _canvas.applyFilter(_canvas, _canvas.rect, o, _filters[0]); //blur 적용
            _canvas.unlock();
        }

        private function RESIZE(e:Event):void {
            setup();
        }
    }

}
import flash.display.Stage;

/**
 * 소용돌이 에너지
 */
class Spire {

    public var centerX:int;
    public var centerY:int;

    public var rotatePower:Number=0.5;
    public var cRotate:Number=Math.cos(rotatePower * Math.PI);
    public var sRotate:Number=Math.sin(rotatePower * Math.PI);

    /**
     * 갱신
     * @param    _x
     * @param    _y
     */
    public function Update(_x:int, _y:int):void {
        centerX=_x;
        centerY=_y;
    }
}

/**
 * 소용돌이 에너지의 희생이 되는 가루
 */
class Powder {

    public var next:Powder; //다음 넘(링크드 리스트)

    public var posX:Number; //현재 위치 
    public var posY:Number;
    public var defX:Number; //최초 위치 
    public var defY:Number; 

    public var life:int; //생명주기 
    public var alpha:Number=0;

    public static var speed:Number=1; //속도 

    public function Powder(_x:Number, _y:Number, _l:int) {
        Set(_x, _y, _l);
    }

    public function Set(_x:Number, _y:Number, _l:int):void {
        posX=_x;
        posY=_y;
        life=_l;
        defX=_x;
        defY=_y;
        alpha=1;
    }

    public function Move(s:Spire):void {
        var rnd:Number=(Math.random() - 0.5) * 2; //1px 내외로 흔들리는 효과를 위해 적용 
        var vecX:Number=(posX - s.centerX); //상대 X위치 
        var vecY:Number=(posY - s.centerY); //상대 Y위치 
        /*
        //cos,sin은 비교적 비싼 비용을 지불해야한다. 그냥 사용하면 안좋음!
           var theta : Number = (90 + s.rotatePower / 2) / 180 * Math.PI;
           var cos : Number = Math.cos(theta);
           var sin : Number = Math.sin(theta);
           var vx : Number = vecX * cos + vecY * -sin;
           var vy : Number = vecX * sin + vecY * cos;
         */
        var vx:Number=vecX * s.cRotate + vecY * s.sRotate; //회전했을때 x값
        var vy:Number=vecX * -s.sRotate + vecY * s.cRotate; //회전했을때 y값 
        var r:Number=Math.sqrt(vx * vx + vy * vy); //회전했을때 중심으로부터 거리 

        vx/=r; //cos
        vy/=r; //sin

        posX+=vx * 4 * speed + rnd; //4를 곱한건 약간 기울어져 있는 효과를 주기 위함 
        posY+=vy * 1 * speed + rnd;

        life--;
        //생명을 다하면 원래 태어났을때 위치로 이동, 생명주기 설정  
        if (life <= 0) {
            posX=defX;
            posY=defY;
            life=1000 + Math.random() * 100; //생명주기 
            alpha=0;
        }
        //점점 밝아지면서 나타나도록 
        if (alpha < 1) {
            alpha+=0.1;
        }
    }
}