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: 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 ryo_2004's forked from: 10만개 입자를 이용한 유체 시뮬레이션 실험 
// forked from jidolstar's 10만개 입자를 이용한 유체 시뮬레이션 실험 
// forked from nulldesign's Liquid10000
package {
	import flash.display.*;
	import flash.events.*;
	import flash.geom.*;
	import flash.utils.*;
	import flash.filters.*;
	
	import net.hires.debug.Stats;
	
	[SWF(width="465", height="465", backgroundColor="0x000000", frameRate="60")];
	/**
	 * 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 = 10000;
		private var bmpDat:BitmapData;
		private var vectorDat:BitmapData;
		private var bmp:Bitmap;
		private var vectorList:Vector.<VectorDat>;
		private var rect:Rectangle;
		private var cTra:ColorTransform;
		private var timer:Timer;
		
		//private var outWidth:int;
		private var outData:Vector.<uint>;
		private var loader:ImageLoader;
		
		public function bitmap_liquid100000_06() {
			
			loader = new ImageLoader();
			loader.addEventListener(Event.COMPLETE, initialize);
			loader.loadImg();	
//			initialize();
		}
		
		private function initialize(e:Event=null):void {
			//stage 관련의 설정
			stage.align=StageAlign.TOP_LEFT;
			stage.scaleMode=StageScaleMode.NO_SCALE;
			stage.frameRate = 60;
			
			//파티클이 렌더링 되는 메인 Bitmap. 
			bmpDat=new BitmapData(465, 465, false, 0x0);
			bmp=new Bitmap(bmpDat);
			addChild(bmp);
			
			//파티클의 가속도를 계산하기 위한 도움 BitmapData로서 perlinNoise가 적용된다. 
			vectorDat= new BitmapData( 28, 28, false, 0x0 );
			seed=Math.floor(Math.random() * 0xFFFF);
			vectorDat.perlinNoise(28, 28, 4, seed, false, true, 2|4, false, offset );
			addChild(new Bitmap(vectorDat)); //만약 이 perlinNoise가 적용된 Bitmap을 보고 싶다면 주석을 풀자 
						
			mapRect = vectorDat.rect;
			mapWidth = vectorDat.width;
			//outWidth = bmpDat.width;
		
			//outData = new Vector.<uint>(bmpDat.width * bmpDat.height, false);	
			mapData = new Vector.<uint>(vectorDat.width * vectorDat.height, true);
		
			//화면크기 
			rect=new Rectangle(0, 0, 465, 465);
			
			//파티클 궤적을 그리기 위함 
			cTra = new ColorTransform(1, 1, 1, .8);
			
			//파티클을 넣기 위한 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();

			
			// overlay
			addChild(loader);
						
			//통계 
			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 var tCounter:int=0;
		private var ep:Point = new Point();
		private var blur:BlurFilter = new BlurFilter(4,4,1);
		private function loop(e:Event):void {
			bmpDat.lock();
		
			//렌더링용 BitmapData를 colorTransform로 어둡게 하여 기존에 그려진 파티클의 궤적을 보이도록 함 
			bmpDat.colorTransform(rect, cTra);
			bmpDat.applyFilter(bmpDat, rect, ep, blur);
			//bmpDat.fillRect(rect, 0x0);
			//outData = bmpDat.getVector(rect);
			
			//outData.length = 0;
			//outData.length = dataLength;
			
			//파티클의 위치를 재계산하여 렌더링한다.
			var col:uint;
			var dots:VectorDat;
			var posX:Number;
			var posY:Number;
			var idx:int;
			
			// 결론 . 파티클에선 벡터가 구린듯?
			for (var i:uint=0; i < nums; i++) {
				dots = vectorList[i];
				
				posX = dots.px;
				posY = dots.py;

				//col = vectorDat.getPixel(dots.px>>4, dots.py>>4);
				//idx = (dots.px>>4)|(dots.py>>4)&mapWidth
				idx = (posX>>4)|(posY>>4);
				col = mapData[idx];
				//dots.next(col);

				posX += (dots.vx += (dots.ax += ((col & 0xff) - 128) * .0005));
				posY += (dots.vy += (dots.ay += ((col >> 8 & 0xff) - 128) * .0005));
							
				//속도와 가속도가 계속 증가하는 것을 방지 
				dots.ax*=.96;
				dots.ay*=.96;
				dots.vx*=.92;
				dots.vy*=.92;
				
				if (posX<0 || posX>465) posX = (posX+465)%465;
				if (posY<0 || posY>465) posY = (posY+465)%465;

				//1*1 pixel을 bitmapData에 렌더링 
				//col = (0xff*transR<<16|0xff*transG<<8|0xff*transB)
				bmpDat.setPixel( posX, posY, 0xffffff );
				dots.px = posX;
				dots.py = posY;
				//idx = (posX|0) + (posY|0)*465;
				//outData[idx] = col;//0xffffffff;				
			}
			//bmpDat.setVector(rect, outData);			
			loader.colorTrans();
			bmpDat.unlock();
			
			if (++tCounter<127)	return;
			tCounter = 0;
			loader.change();			
		}
		
		private var seed:Number = Math.floor( Math.random() * 0xFFFF );
		private var offset:Array = [new Point(), new Point()];
		private var mapData:Vector.<uint> ;
		private var mapRect:Rectangle;
		private var mapWidth:Number;
		//private var vR:Number=0, vG:Number=0, vB:Number=0;		
		private function resetFunc(e:Event) :void{
			//파티클의 가속도를 계산하기 위한 도움 BitmapData로서 perlinNoise를 변경 
			vectorDat.perlinNoise( 20, 20, 3, seed, false, true, 2|4, false, offset );
			offset[0].x += 1.5;
			offset[1].y += 1.5;
			//seed = Math.random()*uint.MAX_VALUE;
			mapData = vectorDat.getVector(mapRect);
			mapData.fixed = true;
			
			//파티클 궤적을 표시하기 위한 부분을 변경(조금씩 색변동이 일어난다) 
			/*
			var dots:VectorDat = vectorList[0];
			vR += .0001 * (dots.px-232)/465;
			vG += .0001 * (dots.py-232)/465;
			vB += .0001 * ((dots.px+dots.py)*.5 -232)/465
			( vR > .2 ) ? vR = .2:
				( vR < -.2 ) ? vR = -.2:0;
			( vG > .2 ) ? vG = .2:
				( vG < -.2 ) ? vG = -.2:0;
			( vB > .2 ) ? vB = .2:
				( vB < -.2 ) ? vB = -.2:0;
							
			cTra.redMultiplier += vR;
			cTra.blueMultiplier += vB;
			cTra.greenMultiplier += 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; 
			( cTra.greenMultiplier > .9 ) ? cTra.greenMultiplier = .9:
				( cTra.greenMultiplier < .5 ) ? cTra.greenMultiplier = .5:cTra.greenMultiplier;

			//loader.bitmapData.colorTransform(rect, cTra);
			*/
			   
		}
	}
}

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;
	
	public function VectorDat( px:Number, py:Number ) {
		this.px = px;
		this.py = py;
	}
}

import flash.events.Event;
import flash.net.*;
import flash.display.*;
import flash.geom.*;
import flash.filters.BlurFilter;
import flash.system.LoaderContext;
class ImageLoader extends Bitmap 
{
	private var rect:Rectangle;
	private var cTra:ColorTransform = new ColorTransform(1,1,1,1,-1,0,1);
	private var colorArr:Array = [-1,0,1,0];
	public function loadImg():void	
	{
		var loader:Loader = new Loader();
		var req:URLRequest = new URLRequest("http://teatime2.cafe24.com/200px-Koch1.jpg");
		loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
		loader.load(req, new LoaderContext(true));
	}
	public function change():void
	{
		colorArr.push(colorArr.shift());
		cTra.redOffset = colorArr[0];
		cTra.blueOffset = colorArr[1];
		cTra.greenOffset = colorArr[2];
	}
	public function colorTrans():void
	{
		bitmapData.colorTransform(rect, cTra);
	}
	private function completeHandler($e:Event):void	
	{
		bitmapData = Bitmap($e.target.content).bitmapData;
		bitmapData.applyFilter(bitmapData, bitmapData.rect, new Point(), new BlurFilter(32,32,1));
		rect = bitmapData.rect;
		width = height = 465;
		blendMode = "overlay";
		dispatchEvent( new Event(Event.COMPLETE) );
	}
}