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

bitmapData를 이용한 태풍

渦、台風っぽく
高速化しないと重いな
ブラーもかけたいかも
じっと見てると目をまわします
/**
 * Copyright jidolstar ( http://wonderfl.net/user/jidolstar )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/zPyr
 */

// 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;
		}
	}
}