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

10만개 입자를 이용한 유체 시뮬레이션 실험

BitmapData를 이용한 파티클 렌더링 속도 테스트 
1. lock, unlock 추가 -> 기존보다 frameRate 2이상 증가 (12)
2. fillRect을 setPixel로 전환 -> 기존보다 frameRate 25~30이상 증가 (40)
3. point를 number로 전환 -> 기존보다 frameRate 10이상 증가 (50)
4. array를 vector로 변환 -> 기존보다 frameRate 변화거의 없음 
5. vector를 linked list로 변환 -> 기존보다 frameRate가 5이상 줄어듬(45)
6. 4로부터 vectorDat 사이즈를 줄임 -> 기존보다 frameRate 10이상 증가(60이상)
@see http://clockmaker.jp/blog/2009/04/particle/
// forked from nulldesign's Liquid10000
package {
	import flash.display.*;
	import flash.events.*;
	import flash.geom.*;
	import flash.utils.*;
	
	import net.hires.debug.Stats;
	
	[SWF(width="465", height="465", backgroundColor="0x000000", frameRate="110")];
	/**
	 * BitmapData를 이용한 파티클 렌더링 속도 테스트 
	 * 1. lock, unlock 추가 -> 기존보다 frameRate 2이상 증가 (12)
	 * 2. fillRect을 setPixel로 전환 -> 기존보다 frameRate 25~30이상 증가 (40)
	 * 3. point를 number로 전환 -> 기존보다 frameRate 10이상 증가 (50)
	 * 4. array를 vector로 변환 -> 기존보다 frameRate 변화거의 없음 
	 * 5. vector를 linked list로 변환 -> 기존보다 frameRate가 5이상 줄어듬(45)
	 * 6. 4로부터 vectorDat 사이즈를 줄임 -> 기존보다 frameRate 10이상 증가(60이상)
	 * @see http://clockmaker.jp/blog/2009/04/particle/
	 */ 
	public class bitmap_liquid100000_06 extends Sprite {
		
		private const nums:uint=100000;
		private var bmpDat:BitmapData;
		private var vectorDat:BitmapData;
		private var randomSeed:uint;
		private var bmp:Bitmap;
		private var vectorList:Vector.<VectorDat>;
		private var rect:Rectangle;
		private var cTra:ColorTransform;
		private var vR:Number;
		private var vG:Number;		
		private var timer:Timer;
		
		public function bitmap_liquid100000_06() {
			initialize();
		}
		
		private function initialize():void {
			//stage 관련의 설정
			stage.align=StageAlign.TOP_LEFT;
			stage.scaleMode=StageScaleMode.NO_SCALE;
			stage.frameRate=110;
			
			//파티클이 렌더링 되는 메인 Bitmap. 
			bmpDat=new BitmapData(465, 465, false, 0x000000);
			bmp=new Bitmap(bmpDat);
			addChild(bmp);
			
			//파티클의 가속도를 계산하기 위한 도움 BitmapData로서 perlinNoise가 적용된다. 
			vectorDat= new BitmapData( 28, 28, false, 0x000000 );
			randomSeed=Math.floor(Math.random() * 0xFFFF);
			vectorDat.perlinNoise(230, 230, 4, randomSeed, false, true, 1 | 2 | 0 | 0);
			//addChild(new Bitmap(vectorDat)); //만약 이 perlinNoise가 적용된 Bitmap을 보고 싶다면 주석을 풀자 
			
			//화면크기 
			rect=new Rectangle(0, 0, 465, 465);
			
			//파티클 궤적을 그리기 위함 
			cTra=new ColorTransform(.8, .8, .9, 1.0);
			vR = 0;
			vG = 0;
			
			//파티클을 넣기 위한 List
			vectorList = new Vector.<VectorDat>(nums, true);
			for (var i:uint=0; i < nums; i++) {
				//파티클 위치
				var px:Number=Math.random() * 465;
				var py:Number=Math.random() * 465;
				//파티클 위치,가속도,속도 정보를 List에 저장 
				vectorList[i] = new VectorDat(px,py);
			}
			
			//지속적인 파티클 렌더링을 위한 loop 함수 호출 
			addEventListener(Event.ENTER_FRAME, loop);
			
			//500ms마다 
			timer = new Timer(500, 0);
			timer.addEventListener(TimerEvent.TIMER, resetFunc);
			timer.start();
			
			//통계 
			addChild(new Stats);
			
			//Flash가 Active될때 동작
			stage.addEventListener(Event.ACTIVATE,function($e:Event):void {stage.frameRate=110}); 
			//Flash가 Deactive될때 중지
			stage.addEventListener(Event.DEACTIVATE,function($e:Event):void {stage.frameRate=0.01});  
		}
		
		private function loop(e:Event):void {
			bmpDat.lock();
			//렌더링용 BitmapData를 colorTransform로 어둡게 하여 기존에 그려진 파티클의 궤적을 보이도록 함 
			bmpDat.colorTransform(rect, cTra);
			
			//파티클의 위치를 재계산하여 렌더링한다.
			var len:uint=vectorList.length;
			var col:Number;
			var dots:VectorDat;
			var posX:Number;
			var posY:Number;
			//trace( dots.px, dots.px>>4)
			for (var i:uint=0; i < len; i++) {
				dots=vectorList[i];
				col=vectorDat.getPixel(dots.px>>4, dots.py>>4);
				dots.ax+=((col >> 16 & 0xff) - 128) * .0005; //적색을 x축 가속도로 사용
				dots.ay+=((col >> 8 & 0xff) - 128) * .0005; //녹색을 y축 가속도로 사용
				dots.vx+=dots.ax;
				dots.vy+=dots.ay;
				dots.px+=dots.vx;
				dots.py+=dots.vy;
				
				posX=dots.px;
				posY=dots.py;
				
				//속도와 가속도가 계속 증가하는 것을 방지 
				dots.ax*=.96;
				dots.ay*=.96;
				dots.vx*=.92;
				dots.vy*=.92;
				
				//stage 밖으로 이동했을 경우 처리. 3항 연산자 처리함 
				(posX > 465) ? dots.px=0 : (posX < 0) ? dots.px=465 : 0;
				(posY > 465) ? dots.py=0 : (posY < 0) ? dots.py=465 : 0;
				
				//1*1 pixel을 bitmapData에 렌더링 
				//bmpDat.fillRect(new Rectangle(dots.pv.x, dots.pv.y, 1, 1), 0xFFFFFF);
				bmpDat.setPixel( dots.px, dots.py, 0xffffff );
			}
			bmpDat.unlock();
		}
		
		private var seed:Number = Math.floor( Math.random() * 0xFFFF );
		private var offset:Array = [new Point(), new Point()];
		private function resetFunc(e:Event) :void{
			//파티클의 가속도를 계산하기 위한 도움 BitmapData로서 perlinNoise를 변경 
			vectorDat.perlinNoise( 14, 14, 3, seed, false, true, 1|2|0|0, false, offset );
			offset[0].x += 1.5;
			offset[1].y += 1.5;
			
			//파티클 궤적을 표시하기 위한 부분을 변경(조금씩 색변동이 일어난다)  
			var dots:VectorDat = vectorList[0];
			vR += .001 * (dots.px-232)/465;
			vG += .001 * (dots.py-232)/465;
			( vR > .01 ) ? vR = .01:
				( vR < -.01 ) ? vR = -.01:0;
			( vG > .01 ) ? vG = .01:
				( vG < -.01 ) ? vG = -.01:0;
			
			cTra.redMultiplier += vR;
			cTra.blueMultiplier += vG;
			( cTra.redMultiplier > .9 ) ? cTra.redMultiplier = .9:
				( cTra.redMultiplier < .5 ) ? cTra.redMultiplier = .5:cTra.redMultiplier;
			( cTra.blueMultiplier > .9 ) ? cTra.blueMultiplier = .9:
				( cTra.blueMultiplier < .5 ) ? cTra.blueMultiplier = .5:cTra.blueMultiplier;         
		}
	}
}

class VectorDat {
	public var vx:Number = 0;
	public var vy:Number = 0;
	public var ax:Number = 0;
	public var ay:Number = 0;
	public var px:Number;
	public var py:Number;
	
	function VectorDat( px:Number, py:Number ) {
		this.px = px;
		this.py = py;
	}
}