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

傾斜プラクティス ver.6 boids化した

傾斜プラクティス ver.6 boids化した

黄色と水色のドットが戦うプログラム
点同士が衝突すると運動エネルギーの少ないほうが消滅します
/**
 * Copyright lagash ( http://wonderfl.net/user/lagash )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/hm0p
 */

// 傾斜プラクティス ver.6 boids化した

// 黄色と水色のドットが戦うプログラム
// 点同士が衝突すると運動エネルギーの少ないほうが消滅します

//-----操作
// mouse drag	地形スクロール
// click		地形隆起/沈降
// [space]		上記隆起/沈降トグル
// [enter]		地形リセット
// [r]			パーティクルリセット
//--------------------------------------------

// 下のグラフは戦況を表しています
//  折れ線:各色のドットが消滅した数
//  横棒:各色ドットの残存数。
// ---------------------------------- 

package {
	import adobe.utils.CustomActions;
	import flash.display.Loader;
    import flash.display.Sprite;
    import flash.display.Shape;
    import flash.display.Bitmap;
	import flash.display.Stage;
	import flash.display.BitmapData;
	import flash.display.DisplayObjectContainer;
	import flash.display.LineScaleMode;
	import flash.display.BlendMode;
	import flash.events.MouseEvent;
	import flash.filters.ColorMatrixFilter;
	import flash.filters.DisplacementMapFilter;
	import flash.geom.Matrix;
    import flash.geom.Rectangle;
    import flash.geom.Point;
	import flash.geom.ColorTransform;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.net.URLRequest;
	import flash.text.TextField;
	import flash.utils.ByteArray;
	import flash.filters.BlurFilter;
	import flash.system.LoaderContext;
	import flash.geom.Vector3D;
	import net.hires.debug.Stats;

	
    public class Partest extends Sprite {

		var main_bmp:Bitmap;
		var groups_bmp:Bitmap;
		var clearDisplay_bmd:BitmapData;
		var bgbmp:Bitmap;
		var bgbmp_source:Bitmap;
		var rotateBmp:Bitmap;
		
		var groupsContainer:Sprite;
		var shape1:Shape;
		var curves:Object;
		var rotationColor:Number;
		
		var baseMatrix: Matrix = new Matrix();
		var baseRect:Rectangle;
		var basePoint:Point;
		var baseColorTransform:ColorTransform;
		var baseColorTransform2:ColorTransform;
		var ColorMatrixFilter1:ColorMatrixFilter;
		var ColorMatrixFilter2:ColorMatrixFilter;
		var keishaMap:BitmapData;
		
		const maxParticles = 600;

		var slopeData_bmd:BitmapData;
        static public var landformData_bmd: BitmapData;
        //private var COLOR: uint = 0xFFFFFF;
        private var seed: int;
        private var mw: int;
        private var mh: int;
        private var arr: Array;
        private var point: Point;
        private var point2: Point;
		
		static public var stageWidth;
		static public var stageHeight;
		var centerX:uint;
		var centerY:uint;
		var onDrag:Boolean=false;
		var onDragX:int=0;
		var onDragY:int = 0;
		var onDragStartX:int = 0;
		var onDragStartY:int = 0;
		var toggleBW:Boolean = true;
		
		private var wholeParticles:Vector.<Particle>=new Vector.<Particle>();
		private var sidesVec=wholeParticles;
		private var groups:Vector.<GroupObject> = new Vector.<GroupObject>();

		private var textDisp:TextField;
		private var bottomBar:Shape;
		private var dyingLate:Bitmap;
		private var yDlShape:Shape;
		private var cDlShape:Shape;
		
		private var stats:Stats;
		
		/* 三角関数高速化
		static public const _TABLE_SIZE:int = 0x10000;
		static public const _PI:Number = Math.PI;
		static public const _TWO_PI:Number = 2 * _PI;
		static public const _TWO_PI_SCALE:Number = _TABLE_SIZE / _TWO_PI;
		static public const _HALF_PI:Number = _PI / 2;
		static public const _table:Vector.<Number> = new function ():Vector.<Number>{
			var table:Vector.<Number> = new Vector.<Number>(_TABLE_SIZE, true);
			for (var i:uint = 0; i < _TABLE_SIZE; i++) {
				table[i] = Math.sin(i / _TWO_PI_SCALE);
			}
			return table;
		};
		*/

        public function Partest() {
			super();
			addEventListener(Event.ADDED_TO_STAGE, addToStageHandlr);
		}

		private function addToStageHandlr(e:Event) {
			removeEventListener(Event.ADDED_TO_STAGE, addToStageHandlr);

 			stage.frameRate = 60;
			//stage.doubleClickEnabled=true;
			stageWidth = stage.stageWidth;
			stageHeight = stage.stageHeight;
			this.buttonMode=this.useHandCursor = true;
			
            landformData_bmd = new BitmapData(stageWidth / 2+1, stageHeight / 2+1);
			main_bmp = new Bitmap(new BitmapData(stage.stageWidth, stage.stageHeight, true, 0xff000000), "auto", true);//bitmap処理用
			main_bmp.alpha = 1;
			main_bmp.blendMode=BlendMode.ADD;
			groups_bmp = new Bitmap(new BitmapData(stage.stageWidth, stage.stageHeight, true, 0x00000000), "auto", true);//bitmap処理用
			groups_bmp.alpha = 1;
			//groups_bmp.filters = [new BlurFilter(32, 32, 2)];
			groups_bmp.blendMode = BlendMode.ADD;
			clearDisplay_bmd = new BitmapData(stage.stageWidth, stage.stageHeight, true, 0x01000000);
			slopeData_bmd = new BitmapData(stage.stageWidth, stage.stageHeight, true, 0xff000000);//bitmap処理用
			bgbmp = new Bitmap(new BitmapData(stage.stageWidth * 3, stage.stageHeight * 3), "auto", true);//bitmap処理用
			bgbmp.x = -stage.stageWidth;
			bgbmp.y = -stage.stageHeight;
			bgbmp_source = new Bitmap(new BitmapData(stage.stageWidth, stage.stageHeight), "auto", true);//bitmap処理用
			rotateBmp = new Bitmap(new BitmapData(stage.stageWidth * 3, stage.stageHeight * 3), "auto", true);//bitmap処理用
			groupsContainer = new Sprite();
			shape1 = new Shape();
			shape1.filters = [new BlurFilter(64, 64, 2)];
			
			textDisp = new TextField();
			textDisp.width=stage.stageWidth;
			textDisp.y = stage.stageHeight-20;
			textDisp.textColor = 0xffffff;
			textDisp.cacheAsBitmap;
			
			bottomBar = new Shape();
			bottomBar.y = stage.stageHeight - 10;
			
			dyingLate = new Bitmap(new BitmapData(stageWidth * .8, 100,true,0x00000000));
			dyingLate.x = (stageWidth - stageWidth * .8) / 2;
			dyingLate.y = stageHeight - 115;
			yDlShape = new Shape();
			cDlShape = new Shape();
			//dyingLate.alpha = .5;
			
			basePoint = new Point(0, 0);
			baseRect = new Rectangle(0, 0, stageWidth, stageHeight);
			baseColorTransform = new ColorTransform;
			baseColorTransform.redMultiplier = .03;
            baseColorTransform.greenMultiplier = .06;
            baseColorTransform.blueMultiplier = .02;
			//baseColorTransform.redOffset = baseColorTransform.greenOffset = baseColorTransform.blueOffset = -10;
			baseColorTransform2 = new ColorTransform;
			baseColorTransform2.redMultiplier = baseColorTransform2.greenMultiplier = baseColorTransform2.blueMultiplier = 5;
			//baseColorTransform2.redOffset = 
            baseColorTransform2.greenOffset = 20;
            //baseColorTransform2.blueOffset = 20;
			
			ColorMatrixFilter1 = new ColorMatrixFilter([
				.03, 0, 0, 0, 0,
				0, .06, 0, 0, 0,
				0, 0, .02, 0, 0,
				0, 0, 0, 1, 0
			]);
			ColorMatrixFilter2 = new ColorMatrixFilter([
				5, 0, 0, 0, 0,
				0, 5, 0, 0, 20,
				0, 0, 5, 0, 0,
				0, 0, 0, 1, 0
			]);
			bgbmp.filters = [ColorMatrixFilter1,ColorMatrixFilter2];
			
			baseMatrix.identity();
            baseMatrix.scale(2,2);
			
            stats = new Stats();
			stats.blendMode = BlendMode.SCREEN;
			
			
			addChild(bgbmp);
			addChild(groups_bmp);
			addChild(main_bmp);
			addChild(stats);
			addChild(dyingLate);
			addChild(bottomBar);
			addChild(textDisp);

            init();
            setMap();
			
			//イベント登録
			//stage.addEventListener(MouseEvent.DOUBLE_CLICK, mouseClickHandlr);
			stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandlr);
			stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandlr);
			stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandlr);
			//stage.addEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandlr);
			stage.addEventListener(Event.ENTER_FRAME, enterframeHandlr);
			stage.addEventListener(KeyboardEvent.KEY_DOWN, function(e:KeyboardEvent) {
				if (e.charCode == 32) toggleBW = (!toggleBW);
				if (e.charCode == 13) setMap();
				if (e.charCode == 114) init();
			} );
			
		}

		private function mouseClickHandlr(e) {
            setMap();
		}
		
		private function mouseDownHandlr(e) {
            onDragX=onDragStartX=e.currentTarget.mouseX;
            onDragY=onDragStartY=e.currentTarget.mouseY;
            onDrag=true;
		}
		
		private function mouseUpHandlr(e) {
			onDrag = false;
		    if (onDragStartX == e.currentTarget.mouseX && onDragStartY == e.currentTarget.mouseY) {
				bgbmp.bitmapData.lock();
				shape1.graphics.clear();
				shape1.graphics.beginFill(0xffffff * uint(toggleBW), .2);
				for (var i = -1; i < 2; i++) for (var j = -1; j < 2; j++) shape1.graphics.drawCircle(e.currentTarget.mouseX+i*stageWidth, e.currentTarget.mouseY+j*stageHeight, 32);
				bgbmp_source.bitmapData.draw(shape1);
				landformData_bmd.draw(bgbmp_source.bitmapData, new Matrix(.5, 0, 0, .5, 0, 0));
				for (i = 0; i < 3; i++) for (j = 0; j < 3; j++) bgbmp.bitmapData.copyPixels( bgbmp_source.bitmapData, baseRect, new Point(i * stageWidth, j * stageHeight));
				bgbmp.bitmapData.unlock();
				
			}
		}
		
		private function mouseMoveHandlr(e) {
			if (!onDrag) return;

			bgbmp.x -=onDragX-e.currentTarget.mouseX;
			bgbmp.y -=onDragY-e.currentTarget.mouseY;
			onDragX = e.currentTarget.mouseX;
			onDragY = e.currentTarget.mouseY;
			
			bgbmp_source.bitmapData.copyPixels(bgbmp.bitmapData, new Rectangle(-bgbmp.x, -bgbmp.y,stageWidth,stageHeight), basePoint);
			landformData_bmd.draw(bgbmp_source.bitmapData, new Matrix(.5, 0, 0, .5, 0, 0));
			for (var i = 0; i < 3; i++) for (var j = 0; j < 3; j++) bgbmp.bitmapData.copyPixels( bgbmp_source.bitmapData, baseRect, new Point(i * stageWidth, j * stageHeight));
			bgbmp.x = -stageWidth;
			bgbmp.y = -stageHeight;

		}
		
		private function mouseWheelHandlr(e:MouseEvent) {
			return;
		}
		
		//初期化
		private function init() {

			var sidePer=0;
			if(sidesVec){
				var tmpYellow=sidesVec.length;
				var tmpCyan=wholeParticles.length-sidesVec.length;
				sidePer=(tmpCyan-tmpYellow)/2;
			}
			
			var currentParticlesLength = wholeParticles.length;
			var px = stage.stageWidth * Math.random();
			var py = stage.stageHeight * Math.random();
			var ppx:Number;
			var ppy:Number;
			for (var i = 0; i < maxParticles-currentParticlesLength; i++) {
				if (Math.random() < .06) {
					px = stage.stageWidth * Math.random();
					py = stage.stageHeight * Math.random();
				}
				do {
					ppx = px + Math.random() * 70 - 35;
					ppy = py + Math.random() * 70 - 35;
				}while((ppx<0 || ppx>stage.stageWidth) && (ppy<0 || ppy>stage.stageHeight))
				wholeParticles.push(new Particle(ppx, ppy));
				wholeParticles[wholeParticles.length-1].side = (wholeParticles[wholeParticles.length-1].yy<stage.stageHeight/2+sidePer)?true:false;
			}
			
		}
		
        function setMap():void{
			landformData_bmd.perlinNoise(mw = landformData_bmd.width >> 2, mh = landformData_bmd.height >> 2, 3, 
			seed = Math.random() * 0xFFFF, true, true, 1,true);
			arr = [point = new Point(), point2 = new Point()];
			
            bgbmp_source.bitmapData.draw(landformData_bmd,baseMatrix);
			for (var i = 0; i < 3; i++)for (var j = 0; j < 3; j++)bgbmp.bitmapData.copyPixels( bgbmp_source.bitmapData, baseRect,new Point(i*stageWidth,j*stageHeight));
			rotateBmp.bitmapData.copyPixels(bgbmp.bitmapData, new Rectangle(0, 0, bgbmp.bitmapData.width, bgbmp.bitmapData.height), basePoint);
			
			keishaMap = new BitmapData(stage.stageWidth, stage.stageHeight, true, 0x00000000);//傾斜データ保存用
                  
        }
				
		//メイン
		private function enterframeHandlr(e){
			var flg_2 = 0;
			textDisp.text = "";
			main_bmp.bitmapData.lock();
			groups_bmp.bitmapData.lock();

			majesticLoop();
			//configureGroup();
			//movingByGroups();
			particlesCollision();
			movingParticles();
			
			drawParticles();

		
			//画面表示系処理
			main_bmp.bitmapData.applyFilter(main_bmp.bitmapData, baseRect, basePoint, new BlurFilter(2, 2, 2));
			main_bmp.bitmapData.unlock();
			groups_bmp.bitmapData.unlock();
			
			//ステータス表示
			//textDisp.text = "yellow:" + sidesVec.length + "(" + yHp + ") / cyan: " + (wholeParticles.length - sidesVec.length) + "(" + cHp + ")  groups: " + groups.length + "  " + gStr + " drawMode:" + ((toggleBW)?"rise":"fall");
			
			
			//stage.removeEventListener(Event.ENTER_FRAME, enterframeHandlr);
		}
		//---------------------------------------------------------------------------

		//大ループ ~全オブジェクトの各個単体処理を纏める
		private function majesticLoop():void {
			wholeParticles.sort(sortParticles);
				function sortParticles(x, y):Number {
					if (x.xx > y.xx) { return 1; } else { return -1; }
					return 0;
				}

			var pl=wholeParticles.length;
			for (var i = 0; i < pl; i++) {
				var tmpObj = wholeParticles[i];
				//ここから呼ぶ
				//flocking(tmpObj);
				flocking2(tmpObj,i);
				moveBySlope(tmpObj);
			}
		}
		
		//---------------------------------------------------------------------------

		//パーティクル表示
		private function drawParticles():void {
			var pl = wholeParticles.length;
			var tmpObj:Particle;
			var col:uint;
			for (var i = 0; i < pl; i++) {
				tmpObj = wholeParticles[i];
				
				var sideColor = 0xee * int(tmpObj.side);
				col = 0xee;// * i / maxParticles;
				col = (0x10000 * sideColor) + (0x100 * col) + (col-sideColor);
				main_bmp.bitmapData.setPixel(tmpObj.xx, tmpObj.yy, col );
			/*	main_bmp.bitmapData.setPixel(tmpObj.xx+2, tmpObj.yy, col );
				main_bmp.bitmapData.setPixel(tmpObj.xx-2, tmpObj.yy, col );
				main_bmp.bitmapData.setPixel(tmpObj.xx, tmpObj.yy+2, col );
				main_bmp.bitmapData.setPixel(tmpObj.xx, tmpObj.yy-2, col );
			*/
			}
		}
		
		//パーティクル移動
		private function movingParticles():void {
			var spdLim = 3;
			
			var pl=wholeParticles.length;
			for (var i = 0; i < pl; i++) {
				var tmpObj = wholeParticles[i];
				var tl=getLineLength(0,0,tmpObj.tx,tmpObj.ty);
				if(tl>spdLim){tmpObj.tx=tmpObj.tx/tl*spdLim;tmpObj.ty=tmpObj.ty/tl*spdLim;}

				tmpObj.xx += tmpObj.tx;
				tmpObj.yy += tmpObj.ty;
				
				//tmpObj.tx *= .99;
				//tmpObj.ty *= .99;

				//画面端はループ
				if (tmpObj.xx < 0 || tmpObj.xx >= stageWidth) { tmpObj.xx = uint(tmpObj.tx < 0) * (stageWidth-1);}
				if (tmpObj.yy < 0 || tmpObj.yy >= stageHeight) { tmpObj.yy = uint(tmpObj.ty < 0) * (stageHeight-1);}
			}
		}
		
		//視野にあるオブジェクトに追従(boids)
		var PI:Number = Math.PI;
		
		private function flocking2(refObj:Particle,num:int):void {
			var tmpGroups:Vector.<Particle> = new Vector.<Particle>();
			var flg1 = true;
			var flg2 = true;
			var i = 1;
			var tmpObj:Particle;
			while( flg1 || flg2 ) {
				if (flg1 && wholeParticles.length - 1 < num + i) flg1 = false;
				if (flg2 && num - i < 0) flg2 = false;
				
				if (flg1) {
					tmpObj = wholeParticles[num + i];
					if(tmpObj.side==refObj.side){
						tmpObj.utilNum = getLineLength(tmpObj.xx, tmpObj.yy, refObj.xx, refObj.yy);
						if (tmpObj.utilNum < 30){
							if(tmpObj.utilNum > 0)tmpGroups.push(tmpObj);
						}else if(tmpObj.xx-refObj.xx>30){flg1 = false;}
					}
				}
				if (flg2) {
					tmpObj = wholeParticles[num - i];
					if(tmpObj.side==refObj.side){
						tmpObj.utilNum = getLineLength(tmpObj.xx, tmpObj.yy, refObj.xx, refObj.yy);
						if (tmpObj.utilNum < 30){
							if(tmpObj.utilNum > 0)tmpGroups.push(tmpObj);
						}else if(refObj.xx-tmpObj.xx>30){flg2 = false;}
					}
				}
				i++;
			}
			
			var refRad = Math.atan2(refObj.ty, refObj.tx);
			var px = 0;
			var py = 0;
			var pcount = 0;
			var pl = tmpGroups.length;
			for (var i = 0; i < pl; i++) {
				var tmpObj = tmpGroups[i];
				var tmpRad = Math.atan2(tmpObj.yy - refObj.yy, tmpObj.xx - refObj.xx);
				var agl_Rad = tmpRad - refRad;
				var norm_Rad = (Math.abs(agl_Rad) > PI)?(PI * 2) - Math.abs(agl_Rad):Math.abs(agl_Rad);
				if (norm_Rad < PI / 2) {
					var a = (tmpObj.utilNum>18)?1:-1;
					px += a*(tmpObj.xx - refObj.xx)/tmpObj.utilNum;
					py += a*(tmpObj.yy - refObj.yy)/tmpObj.utilNum;
					pcount++;
				}
			}
			if (pcount == 0) { return };
			refObj.tx += px / pcount;
			refObj.ty += py / pcount;
		}

		private function flocking(refObj:Particle):void {
			var tmpGroups = wholeParticles.filter(sideCheck, null);
				function sideCheck(item:Particle, index:int, vector:Vector.<Particle>):Boolean {
					return (item.side == refObj.side);
				}
				
   			tmpGroups=wholeParticles.filter(tmpGroupsCheck,null);
				function tmpGroupsCheck(item:Particle, index:int, vector:Vector.<Particle>):Boolean {
					item.utilNum = getLineLength(item.xx, item.yy, refObj.xx, refObj.yy);
					if (item.utilNum<50 && item.utilNum>0 && item.side==refObj.side) { 
					    return true;
					}
					return false;
				}
			
			
			//return;
			
			var refRad = Math.atan2(refObj.ty, refObj.tx);
			var px = 0;
			var py = 0;
			var pcount = 0;
			var pl = tmpGroups.length;
			for (var i = 0; i < pl; i++) {
				var tmpObj = tmpGroups[i];
				var tmpRad = Math.atan2(tmpObj.yy - refObj.yy, tmpObj.xx - refObj.xx);
				var agl_Rad = tmpRad - refRad;
				var norm_Rad = (Math.abs(agl_Rad) > PI)?(PI * 2) - Math.abs(agl_Rad):Math.abs(agl_Rad);
				if (norm_Rad < PI / 1.5) {
					var a = (tmpObj.utilNum>20)?1:-1;
					px += a*(tmpObj.xx - refObj.xx)/tmpObj.utilNum;
					py += a*(tmpObj.yy - refObj.yy)/tmpObj.utilNum;
					pcount++;
				}
			}
			if (pcount == 0) { return };
			refObj.tx += px / pcount;
			refObj.ty += py / pcount;
		}
		
		//傾斜による影響
		private function moveBySlope(tmpObj:Particle):void {
			var sideColor = 0xee * int(tmpObj.side);
			var col = 0xee;// * i / maxParticles;
			col = (0x10000 * sideColor) + (0x100 * col) + (col-sideColor);
			
			//傾斜値を取得
			var vec = getSlopeVector(tmpObj.xx, tmpObj.yy);
			tmpObj.vec = vec;
		
			tmpObj.tx += vec.x*.5;
			tmpObj.ty += vec.y*.5;
					
		
		}
		
			//傾斜マップから傾きベクトルを取得
			private function getSlopeVector(xx:int, yy:int):Point {
				var tmpCol = slopeData_bmd.getPixel32(xx, yy);
				if (landformData_bmd.getPixel32(xx>>1, yy>>1)!=slopeData_bmd.getPixel32(xx, yy)) tmpCol=setMapPoint(xx,yy);
				var bX = tmpCol >>> 16;
				var bY = tmpCol & 0xffff;
				
				var dx = int(uint((((bX&0x8000)<<16)>>16)+(bX&0x7fff)))*.00001;
				var dy = int(uint((((bY & 0x8000) << 16) >> 16) + (bY & 0x7fff))) * .00001;
				
				return new Point(dx, dy);
			}
		
		//衝突判定と影響
		var	frameCnt:uint = 0;
		var yDl:uint = 0;
		var cDl:uint = 0;
		var beforeY:uint = 0;
		var beforeC:uint = 0;
		private function particlesCollision():void {
			var col;
			var tmpTx;
			var tmpTy;
			
			
			var pl = wholeParticles.length;
			var mHP = 0;
			
			for (var i = 0; i < pl; i++) {
				var tmpObj = wholeParticles[i];
				
				var sideColor = 0xee * int(tmpObj.side);
				col = 0xee;// * i / maxParticles;
				col = (0x10000 * sideColor) + (0x100 * col) + (col-sideColor);
				
				
				//当たり判定
				if (i != 0) {
					var hitcnt = i;
					while (hitcnt) {
						hitcnt--;
						if ( tmpObj.xx - wholeParticles[hitcnt].xx > 3) {
							break;
						}
						if( Math.abs(tmpObj.yy - wholeParticles[hitcnt].yy) < 3){// && tmpObj.side!=wholeParticles[hitcnt].side) {
							var tmpCol=0x666666;
							if (tmpObj.side != wholeParticles[hitcnt].side) {
								
								tmpObj.hp = getHP(tmpObj);
								wholeParticles[hitcnt].hp = getHP(wholeParticles[hitcnt]);
								
								var dm = tmpObj.getTl() - wholeParticles[hitcnt].getTl();
								if (dm > 0) { wholeParticles[hitcnt].hp -= dm; } else { tmpObj.hp += dm; }
								tmpCol=0xff0000;
 
							}
                                for (var exp = 1; exp < 4;exp++){
									main_bmp.bitmapData.setPixel(tmpObj.xx - exp, tmpObj.yy-exp, tmpCol );
									main_bmp.bitmapData.setPixel(tmpObj.xx + exp, tmpObj.yy+exp, tmpCol );
									main_bmp.bitmapData.setPixel(tmpObj.xx-exp, tmpObj.yy + exp, tmpCol );
									main_bmp.bitmapData.setPixel(tmpObj.xx+exp, tmpObj.yy - exp, tmpCol );
								}
								
							//var tmpTl = tmpObj.getTl()+wholeParticles[hitcnt].getTl();
							tmpTx = (tmpObj.tx*tmpObj.hp - wholeParticles[hitcnt].tx*wholeParticles[hitcnt].hp);///tmpTl;
							tmpTy = (tmpObj.ty*tmpObj.hp - wholeParticles[hitcnt].ty*wholeParticles[hitcnt].hp);///tmpTl;
							tmpObj.tx += tmpTx / tmpObj.hp;
							tmpObj.ty += tmpTy / tmpObj.hp;
							wholeParticles[hitcnt].tx -= tmpTx / wholeParticles[hitcnt].hp;
							wholeParticles[hitcnt].ty -= tmpTy / wholeParticles[hitcnt].hp;
							
						}
						break;
					}
				}
				
				mHP = (tmpObj.hp > mHP)?tmpObj.hp:mHP;
			}
			
			
			centerX /= wholeParticles.length;
			centerY /= wholeParticles.length;
			
			var yHp:Number=0;
			var cHp:Number = 0;
			
			//パーティクルの整理
			wholeParticles=wholeParticles.filter(hpCheck,null);
				function hpCheck(item:Particle, index:int, vector:Vector.<Particle>):Boolean {
					
					if (item.hp<=0) {
					    if (item.groupFlg) item.group.removeMember(item);
						yDl += (tmpObj.side)?1:0;
						cDl += (!tmpObj.side)?1:0;
						sideColor = 0xee * int(tmpObj.side);
						col = 0xee;// * i / maxParticles;
						col = (0x10000 * sideColor) + (0x100 * col) + (col-sideColor);
						for ( exp = 1; exp < 20;exp++){
							main_bmp.bitmapData.setPixel(item.xx - exp, item.yy, col );
							main_bmp.bitmapData.setPixel(item.xx + exp, item.yy, col );
							main_bmp.bitmapData.setPixel(item.xx, item.yy + exp, col );
							main_bmp.bitmapData.setPixel(item.xx, item.yy - exp, col );
						}
					    return false; 
					}
					return true;
				}
			frameCnt++;
			if(frameCnt>8){
				dyingLate.bitmapData.scroll(5, 0);
				yDlShape.graphics.clear();
				cDlShape.graphics.clear();
				
				yDlShape.graphics.beginFill(0xffff00, .3);
				//yDlShape.graphics.lineStyle(.5, 0xffff00, .5);
				yDlShape.graphics.moveTo(5, 100-beforeY*3);
				yDlShape.graphics.lineTo(0, 100-yDl*3);
				yDlShape.graphics.lineTo(0, 100);
				yDlShape.graphics.lineTo(5, 100);
				cDlShape.graphics.beginFill(0x00ffff, .3);
				//cDlShape.graphics.lineStyle(.5, 0x00ffff, .5);
				cDlShape.graphics.moveTo(5, 100-beforeC*3);
				cDlShape.graphics.lineTo(0, 100-cDl * 3);
				cDlShape.graphics.lineTo(0, 100);
				cDlShape.graphics.lineTo(5, 100);
				beforeY = yDl;
				beforeC = cDl;
				dyingLate.bitmapData.draw(yDlShape,new Matrix(1,0,0,1,5,0));
				dyingLate.bitmapData.draw(cDlShape,new Matrix(1,0,0,1,5,0));
				//for (i = 100; i > 100 - yDl*3 ;i--)dyingLate.bitmapData.setPixel32(1, i, 0x3000ffff);
				//for (i = 100; i > 100 - cDl*3 ;i--) dyingLate.bitmapData.setPixel32(1, i, 0x30ffff00);
				yDl=cDl=frameCnt = 0;
			}
				
			sidesVec=wholeParticles.filter(sideCheck,null);
				function sideCheck(item:Particle, index:int, vector:Vector.<Particle>):Boolean {
					if (item.side==false) { return false; }
					return true;
				}
				
				
			bottomBar.graphics.clear();
			bottomBar.graphics.beginFill(0xeeee00, .5);
			bottomBar.graphics.drawRect((stageWidth-stageWidth * .8)/2, 0, (sidesVec.length / maxParticles) * (stageWidth), 3);
			bottomBar.graphics.beginFill(0x00eeee, .5);
			bottomBar.graphics.drawRect((stageWidth-stageWidth * .8)/2, 6, ((wholeParticles.length - sidesVec.length) / maxParticles) * (stageWidth), 3);
			bottomBar.graphics.endFill();

           //パーティクルのリセット判定
			//if(wholeParticles.length<maxParticles*.1 || sidesVec.length<10 || wholeParticles.length-sidesVec.length<10)init();
			//textDisp.appendText(mHP);
			
			
		}
		
			private function getHP(tmpObj:Particle):Number {
				var v1 = new Point(tmpObj.tx, tmpObj.ty);
				var v2 = new Point(tmpObj.vec.x, tmpObj.vec.y);
				var v3 = v1.add(v2);
				var at1 = Math.atan2(tmpObj.ty, tmpObj.tx);
				var at2 = Math.atan2(v3.y, v3.x);
				
				var ret= (Math.abs(at1 - at2) < Math.PI / 2)?v3.length:(v1.length - v3.length);
				ret = (ret > 0)?ret:1;
				
				return ret;
				//return (v1.add(v2)).length;
			}
		
		//グループ化判定
		private function configureGroup():void {
			
			var pl=wholeParticles.length;
			for (var i = 0; i < pl; i++) {
				
				var tmpObj = wholeParticles[i];
				
				//所属グループチェック
				if(tmpObj.groupFlg){
					if (getLineLength(tmpObj.group.ox, tmpObj.group.oy, tmpObj.xx, tmpObj.yy) > 80) {
						tmpObj.group.removeMember(tmpObj);
						tmpObj.groupFlg = false;
					}
				}else if (!tmpObj.groupFlg) {
					if (groups.length == 0) {
						var newGrp = new GroupObject();
						newGrp.side = tmpObj.side;
						newGrp.addMember(tmpObj);
						tmpObj.group = newGrp;
						tmpObj.groupFlg = true;
						groups.push(newGrp);
					}else {
						var mostNearGroup;
						var mNGLength=70;
						var gl = groups.length;
						for (var gId = 0; gId < gl; gId++) {
							var tmpGrp = groups[gId];
							var tmpLength = getLineLength(tmpGrp.ox, tmpGrp.oy, tmpObj.xx, tmpObj.yy);
							if ((!mNGLength || mNGLength > tmpLength) && tmpGrp.side==tmpObj.side) {
								mNGLength = tmpLength;
								mostNearGroup = tmpGrp;
							}
						}
						
						if (mNGLength < 70) {
							mostNearGroup.addMember(tmpObj);
							tmpObj.group = mostNearGroup;
							tmpObj.groupFlg = true;
						}else {
							newGrp = new GroupObject();
							newGrp.side = tmpObj.side;
							newGrp.addMember(tmpObj);
							tmpObj.group = newGrp;
							tmpObj.groupFlg = true;
							groups.push(newGrp);
						}
					}
				}
			}
		}
		
		//パーティクルのグループによる影響
		private function movingByGroups():void {
			var vec;
			var tmpTx;
			var tmpTy;
			
			groups_bmp.bitmapData.copyPixels(clearDisplay_bmd, baseRect, basePoint);
			
			//グループの整理
   			groups=groups.filter(groupsCheck,null);
				function groupsCheck(item:GroupObject, index:int, vector:Vector.<GroupObject>):Boolean {
				    item.calc();
					
					if (item.length<=4) { 
					    for (var gId in item.members) item.members[gId].groupFlg = false;
						if (item.shape.root) groupsContainer.removeChild(item.shape);
					    return false;
					}
					if (!item.shape.root) groupsContainer.addChild(item.shape);
					return true;
				}
				
			var gmLength=0;
			//パーティクルのグループ化動作
			for (var gId in groups) {
				var tmpGrp = groups[gId];
				gmLength += tmpGrp.length;
				
				vec = getSlopeVector(tmpGrp.ox, tmpGrp.oy);
				tmpGrp.tx += vec.x;
				tmpGrp.ty += vec.y;

				//グループ同士の当たり判定
				for(var hitId in groups) {
					if (gId == hitId) break;
						if ( tmpGrp.shape.hitTestObject(groups[hitId].shape)) {// && tmpObj.side!=wholeParticles[hitcnt].side) {
							var tmpTl = getLineLength(tmpGrp.ox, tmpGrp.oy, groups[hitId].ox, groups[hitId].oy);
							tmpTx = (tmpGrp.ox*tmpGrp.length - groups[hitId].ox*groups[hitId].length)/(tmpTl*tmpTl);
							tmpTy = (tmpGrp.oy*tmpGrp.length - groups[hitId].oy*groups[hitId].length)/(tmpTl*tmpTl);
							tmpGrp.tx += tmpTx/tmpGrp.length;
							tmpGrp.ty += tmpTy/tmpGrp.length;
							groups[hitId].tx -= tmpTx/groups[hitId].length;
							groups[hitId].ty -= tmpTy/groups[hitId].length;
							
						}
				}
				//var spdLim = 1000;
				//tl=getLineLength(0,0,tmpGrp.tx,tmpGrp.ty);
				//if (tl > spdLim) { tmpGrp.tx = (tmpGrp.tx / tl) * spdLim; tmpGrp.ty = (tmpGrp.ty / tl) * spdLim; }
				
				var tmpLx;
				var tmpLy;
				var tmpL;
				for ( var i in tmpGrp.members) {
					var tmpObj = tmpGrp.members[i];
				
				//	グループ中心点へ寄っていく処理
				/*	tmpLx=tmpGrp.ox - tmpObj.xx;
					tmpLy=tmpGrp.oy - tmpObj.yy;
					tmpL=Math.sqrt(Math.pow(tmpLx, 2) + Math.pow(tmpLy, 2));
					tmpObj.tx += (tmpLx / tmpL) >> 4;
					tmpObj.ty += (tmpLy / tmpL) >> 4;
				*/	
					//グループ進行方向とパーティクルの進行方向が異なる時に、作用させる
					if (tmpObj.tx * tmpGrp.tx < 0) tmpObj.tx += tmpGrp.tx;
					if (tmpObj.ty * tmpGrp.ty < 0) tmpObj.ty += tmpGrp.ty;
				}
				
				//凸包計算
				//tmpGrp.Compute();				
				//groups_bmp.bitmapData.draw(tmpGrp.shape);
			}
		}
		
		
		
		//---------------------------------------------------------------------------
        function setMapPoint(tmpX,tmpY):uint{
			var col = landformData_bmd.getPixel(tmpX >> 1, tmpY >> 1);
			
			var dx = 0;
			var dy = 0;
			
			for (var py = -1; py < 2; py++){
				for (var px = -1; px < 2; px++) {
					
					if (px == 0 && py == 0) continue;
					
					var ppx = tmpX + px;
					var ppy = tmpY + py;
					
					if (ppx < 0 || ppx >= stageWidth) { ppx = int(ppx<0)* (stageWidth-1); }
					if (ppy < 0 || ppy >= stageHeight){ ppy = int(ppy<0)* (stageHeight-1);}
					
					var tmpcol = landformData_bmd.getPixel(ppx >> 1, ppy >> 1);
					//slopeData_bmd.setPixel(ppx, ppy, tmpcol);
					
					if (px*px + py*py == 1) {
						dx += (col - tmpcol) * px;
						dy += (col - tmpcol) * py;
					}else {
						dx += (col - tmpcol) * px*.7;
						dy += (col - tmpcol) * py*.7;
					}
				}
			}
			slopeData_bmd.setPixel(tmpX, tmpY, col);
			col = uint((uint((uint(dx/5)&0x80000000)>>>16)+(uint(dx/5)&0x7fff)<<16)+uint((uint(dy/5) & 0x80000000) >>> 16) + (uint(dy/5) & 0x7fff));
			keishaMap.setPixel32(tmpX, tmpY, col);
			return col;
		}

		
		//
		function getLineLength(x1:Number,y1:Number,x2:Number,y2:Number):Number
		{
			var vx=x1-x2;
			var vy=y1-y2;
			var vl=Math.sqrt(Math.pow(vx,2)+Math.pow(vy,2));
			return vl;
		}
		

    }
}

	class bugfix {
		function bugfix():void {
		}
	}
	
	import adobe.utils.ProductManager;
	import flash.display.Shader;
	import flash.geom.Point;
	import flash.geom.Vector3D;
	import flash.display.Shape;
	import flash.utils.ByteArray;
	
	class Particle extends bugfix{
		
		var xx:Number=0;
		var yy:Number=0;
		var tx:Number=0;
		var ty:Number=0;
		var dl:Number = 0;
		var hp:int;
		var side:Boolean;
		var group:GroupObject;
		var groupFlg:Boolean;
		var vec:Point;
		var utilNum:Number;
		
		function Particle(... args):void {
			xx = args[0];
			yy = args[1];
			var sd;
			tx = Math.cos(sd=Math.random() * Math.PI * 2);
			ty = Math.sin(sd);
			groupFlg = false;
			vec = new Point();
			hp = 1;
		}
		
		function getTl():Number {
			return Math.sqrt(Math.pow(tx,2)+Math.pow(ty,2));
		}
	}
	
	class GroupObject extends bugfix{
		var members:Vector.<Particle> = new Vector.<Particle>();
		var mLength:uint;
		var px:Number;
		var py:Number;
		var ox:Number;
		var oy:Number;
		var ttx:Number;
		var tty:Number;
		var tx:Number;
		var ty:Number;
		var side:Boolean;
		var shape:Shape;
		
		function GroupObject():void {
			mLength = px = py = ox = oy = tx = ty = 0;
			shape = new Shape();
			shape.cacheAsBitmap = true;
		}
		
		function calc() {
			mLength = members.length;
			//if (mLength < 1) return;
			
			px = py = ttx = tty = 0;
			for (var i in members) {
				px += members[i].xx;
				py += members[i].yy;
				ttx += members[i].tx;
				tty += members[i].ty;
			}
			ox = px / mLength;
			oy = py / mLength;
			tx = ttx / mLength;
			ty = tty / mLength;
			//Compute();
		}
		
		function addMember(p:Particle) {
			members.push(p);
			mLength = members.length;
			
			px += p.xx;
			py += p.yy;
			ox = px / mLength;
			oy = py / mLength;
			
			ttx += p.tx;
			tty += p.ty;
			tx = ttx / mLength;
			ty = tty / mLength;
			//Compute();
		}

		function removeMember(p:Particle) {
			members.splice(members.indexOf(p), 1);
			mLength = members.length;
			
			px -= p.xx;
			py -= p.yy;
			ox = px / mLength;
			oy = py / mLength;
			
			ttx -= p.tx;
			tty -= p.ty;
			tx = ttx / mLength;
			ty = tty / mLength;
			//Compute();
		}
		
		function get length():uint {
			mLength = members.length;
			return mLength;
		}
		
		//------------------------------------------------------------------------------------------------
		//QuickHull   via http://asura.iaigiri.com/OpenGL/gl50.htmlのコードを元にさせていただいてます
		//------------------------------------------------------------------------------------------------
		
		var m_Points:Vector.<Point> = new Vector.<Point>();
		var m_Ignore:Vector.<Boolean> = new Vector.<Boolean>();
		var m_UpperHull:Vector.<Boolean> = new Vector.<Boolean>();
		var m_EdgeIndex:Vector.<Array> = new Vector.<Array>();

		//-------------------------------------------------------------------------------------------------
		// Desc : 凸包を求める
		function Compute():void
		{
			shape.graphics.clear();

			m_Points.length = m_Ignore.length = m_UpperHull.length = m_EdgeIndex.length = 0;
			members.forEach(setMPoints, null);
				function setMPoints(item:Particle, idx:int, vect:Vector.<Particle>) {
					m_Points.push(new Point(item.xx,item.yy));
				}
			m_Ignore.length = m_UpperHull.length = m_Points.length;
			
			if (m_Points.length < 3) return;
			
			// 最初の稜線を求める
			var axis:Array = FindFirstEdge();

			// 稜線が見つからなかったら終了
			if ( axis[0] == -1 && axis[1] == -1 ) return;
			
			// 稜線を追加
			//m_RenderingFlag.push( false );
			//axis[2] = false;
			m_EdgeIndex.push( axis ) ;
			
			// 上側の領域と下側の領域に分ける
			CheckUpperOrLower( axis );

			// 再帰呼び出しによって凸包を求める
			RecursiveCallCompute( axis, true );		// 上側の領域
			RecursiveCallCompute( axis, false );	// 下側の領域
			
			//shape.graphics.lineStyle(2, 0x0000ff,1);
			//shape.graphics.moveTo(m_Points[axis[0]].x, m_Points[axis[0]].y);
			//shape.graphics.lineTo(m_Points[axis[1]].x, m_Points[axis[1]].y);

			RenderConvexHull();
		}

		//------------------------------------------------------------------------------------------------
		// Desc : 最初の稜線を求める
		function FindFirstEdge():Array
		{
			var index:Array=[0, 0];
			var max:Point, min:Point;

			// 点の数が2よりも小さい場合は-1を返して終了
			if ( m_Points.length < 4 ) 
				return [ -1, -1 ];

			// 初期化
			max = min  = m_Points[0];

			// x座標が最大と最小となる二つの点を求める
			for ( var i=0; i<m_Points.length; i++ )
			{
				// 最小値
				if ( m_Points[i].x < min.x ) 
				{
					index[0] = i;
					min = m_Points[i];
				}
				// 最大値
				if ( m_Points[i].x > max.x )
				{
					index[1] = i;
					max = m_Points[i];
				}
			}

			// 算出結果
			return index;
		}

		//-------------------------------------------------------------------------------------------------
		// Desc : 計算関数を再帰呼び出し
		function RecursiveCallCompute( index:Array, uh:Boolean ):void
		{
			var edge1:Array = [];
			var edge2:Array = [];
			var UpperHull = uh;
			
			// 最も遠い点を求める
			var farestPoint:int = FarestPointFromEdge( index, UpperHull );
			
			// 点が見つからなかった場合は終了
			if ( farestPoint == -1 ) { return;}

			// 三角形を形成する3点は処理から外す
			m_Ignore[index[0]] = true;
			m_Ignore[index[1]] = true;
			m_Ignore[farestPoint] = true;

			// デバッグ用
			//m_Colors[farestPoint] = Vector4f( 0.0f, 1.0f, 1.0f, 1.0f );

			// 三角形内部にある点を処理の対象から外す
			for ( var i=0; i<m_Points.length; i++ )
			{
				if (m_Ignore[i] == true) continue;
				
				var result:Boolean = IsInsideOfTriangle( 
					m_Points[index[0]],
					m_Points[index[1]],
					m_Points[farestPoint],
					m_Points[i] );

				// 内部にあった場合
				if ( result ) { m_Ignore[i] = true;}
			}

			// 凸包の描画用
			if (m_EdgeIndex.indexOf([index[0], index[1], true]) > -1) { trace("!"); m_EdgeIndex[m_EdgeIndex.indexOf([index[0], index[1], true])][2] = false; }
			if (m_EdgeIndex.indexOf([index[1], index[0], true]) > -1){ trace("!");m_EdgeIndex[m_EdgeIndex.indexOf([index[1], index[0], true])][2] = false;}
			index[2] = false;

			// 稜線を追加
			edge1 = [index[0], farestPoint, true];
			edge2 = [farestPoint, index[1], true];
			m_EdgeIndex.push( edge1 );
			m_EdgeIndex.push( edge2 );

			// 再帰呼び出し
			RecursiveCallCompute( edge1, UpperHull ); 
			RecursiveCallCompute( edge2, UpperHull ); 

			return;
		}

		//-------------------------------------------------------------------------------------------------
		// Desc : 稜線に向かって垂線を下ろしたとき,垂線の長さが最大となる点のインデックスを返す
		function FarestPointFromEdge( index:Array, UpperHull:Boolean ):int
		{
			var t = 0;
			var v1:Point, v2:Point, v3:Point, v:Point;
			var max = -1;
			var result:int = -1;

			// 稜線
			v1 = m_Points[index[0]];
			v2 = m_Points[index[1]];
			v = new Point();
			var mv1 = new Point();

			for ( var i=0; i<m_Points.length; i++ )
			{
				// 稜線を形成する点は処理の対象外
				if ( index[0] == i ) continue;
				if ( index[1] == i ) continue;

				// 領域が異なる場合も処理の対象外
				if ( m_UpperHull[i] != UpperHull ) continue;

				// すでに処理されている場合も処理の対象外
				if ( m_Ignore[i] ) continue;
				
				v3 = m_Points[i];

				// 上側の領域の場合
				if ( UpperHull )
				{
					if ( LineQuation(v1, v2, v3) < 0 ) continue;
				}else{// 下側の領域の場合
					if ( LineQuation(v1, v2, v3) > 0 ) continue;	
				}
				
				// 垂線の足の座標
				var Line_v1v2:Point = getLine(v1, v2);
				var CrossLine_v1v2v3 = getCrossLine(v1, v2, v3);
				v = getCrossPoint2Lines(Line_v1v2.x, Line_v1v2.y, CrossLine_v1v2v3.x, CrossLine_v1v2v3.y);
				
				// 垂線の長さを求める
				var d = Point.distance(v, v3);
				
				// 最大値とインデックスの更新
				if ( d > max )
				{
					max = d;
					mv1 = v;
					result = i;
				}
			}
			
			/*垂線表示
					if (result != -1) {
					shape.graphics.lineStyle(1,0xffffff,.5);
					//shape.graphics.drawCircle(mv1.x, mv1.y,2);
					shape.graphics.moveTo(mv1.x, mv1.y);
					shape.graphics.lineTo(m_Points[result].x, m_Points[result].y);
					//shape.graphics.lineStyle(.5, 0xffffff,.2);
					//shape.graphics.drawCircle(m_Points[index[0]].x, m_Points[index[0]].y,1);
					//shape.graphics.lineTo(m_Points[index[1]].x, m_Points[index[1]].y);
					//shape.graphics.drawCircle(m_Points[index[1]].x, m_Points[index[1]].y,1);
					//shape.graphics.lineTo(m_Points[result].x, m_Points[result].y);
					//shape.graphics.lineTo(m_Points[index[0]].x, m_Points[index[0]].y);
				}
			*/

			// インデックスを返す
			return result;
		}

		//------------------------------------------------------------------------------------------------
		// Desc : 直線の方程式
		function LineQuation( v1:Point, v2:Point, v3:Point ):Number
		{
			
			var ma = (v2.x - v1.x);
			var mb = (v2.y - v1.y);

			// 傾き
			var m = 0.0;
			if ( ma != 0 ) m = mb/ma;
			
			// 直線の方程式に3点の座標を代入した結果を返す
			//return (( v3.y - v1.y ) -  m * (v3.x - v1.x));
			
			
			//外積はこっち
			return -((v3.x - v1.x) * (v2.y - v1.y) - (v2.x - v1.x) * (v3.y - v1.y));
		}
		//x1*y2-x2*y1 
		//------------------------------------------------------------------------------------------------
		// Desc : 上側の領域か下側の領域かをチェックする
		function CheckUpperOrLower( index:Array ):void
		{
			var a:Point = m_Points[index[0]];
			var b:Point = m_Points[index[1]];

			// すべての点を調べる
			var c:Point;
			for ( var i=0; i<m_Points.length; i++ )
			{
				c = m_Points[i];


				// 上側の領域
				if ( LineQuation(a, b, c) > 0 )
				{
					m_UpperHull[i] = true;
				}
				// 下側の領域
				else
				{
					m_UpperHull[i] = false;
				}
			}
		}

		//-------------------------------------------------------------------------------------------------
		// Desc : 三角形内部に点があるかないかを判定。内部ならばture,外部ならばfalseを返す
		function IsInsideOfTriangle( v1:Point, v2:Point, v3:Point, point:Point ):Boolean
		{
			var d0:Vector3D, d1:Vector3D;
			var cr:Number;
			var result:Array=[ 0, -1, 1 ];

			// 三角形を形成する3点a, b, c
			var a:Vector3D=new Vector3D(v1.x, v1.y, 0);
			var b:Vector3D=new Vector3D(v2.x, v2.y, 0);
			var c:Vector3D=new Vector3D(v3.x, v3.y, 0);

			// 判定点p
			var p:Vector3D=new Vector3D(point.x, point.y, 0);

			// 法線ベクトルを算出
			var n:Vector3D = a.crossProduct( b );
			n.normalize();

			/// 符号を調べる
			// 1
			d0 = p;d0.decrementBy(a);
			d1 = b;d1.decrementBy(a);
			cr = n.dotProduct(d0.crossProduct( d1 ));
			result[0] = (cr==0)?0:cr/Math.abs(cr);

			// 2
			d0 = p;d0.decrementBy(b);
			d1 = c;d1.decrementBy(b);
			cr = n.dotProduct(d0.crossProduct( d1 ));
			result[1] = (cr==0)?0:cr/Math.abs(cr);

			// 3
			d0 = p;d0.decrementBy(c);
			d1 = a;d1.decrementBy(c);
			cr = n.dotProduct(d0.crossProduct( d1 ));
			result[2] = (cr==0)?0:cr/Math.abs(cr);

			// 符号がすべて同じだった場合は内部
			if ( result[0] == result[1] == result[2])return true;

			// 符号が一か所でも違えば外部
			return false;
		}

		//------------------------------------------------------------------------------------------------
		// Desc : 凸包を描画
		function RenderConvexHull():void
		{
			if(m_EdgeIndex.length<3)return;
			shape.graphics.beginFill((0x10000 * 0xee * int(side)) + (0x100 * 0xee) + (0xee-0xee * int(side)), .04);
			shape.graphics.lineStyle(.1, (0x10000 * 0xee * int(side)) + (0x100 * 0xee) + (0xee-0xee * int(side)), .01);

			var drawPoint:Object = new Object();
			for ( var i:int=0; i<m_EdgeIndex.length-1; i++ )
			{
				if ( m_EdgeIndex[i][2] )
				{
					drawPoint[String(m_EdgeIndex[i][0])]=m_Points[m_EdgeIndex[i][0]];
					drawPoint[String(m_EdgeIndex[i][1])]=m_Points[m_EdgeIndex[i][1]];
				}
			}
			var dPoints:Vector.<Point> = new Vector.<Point>();
			for (var j:String in drawPoint) {
				dPoints.push(drawPoint[j]);
			}
			
			dPoints.sort(sortDP);
				function sortDP(a,b) {
					if (Math.atan2(a.x-ox,a.y-oy) < Math.atan2(b.x-ox,b.y-oy)) return -1;
					if (Math.atan2(a.x-ox,a.y-oy) > Math.atan2(b.x-ox,b.y-oy)) return 1;
					return 0;
				}
				
			shape.graphics.moveTo((dPoints[0].x + dPoints[dPoints.length-1].x) / 2, (dPoints[0].y + dPoints[dPoints.length-1].y) / 2);
			for (i = 0; i < dPoints.length-1; i++) {
				shape.graphics.curveTo(dPoints[i].x, dPoints[i].y,(dPoints[i].x + dPoints[i + 1].x) / 2, (dPoints[i].y + dPoints[i+ 1].y) / 2);
			}
				shape.graphics.curveTo(dPoints[i].x, dPoints[i].y, (dPoints[0].x + dPoints[dPoints.length - 1].x) / 2, (dPoints[0].y + dPoints[dPoints.length - 1].y) / 2);

                        shape.graphics.endFill();
			shape.graphics.lineStyle(.1, (0x10000 * 0xee * int(side)) + (0x100 * 0xee) + (0xee-0xee * int(side)), .05);
			shape.graphics.moveTo(dPoints[dPoints.length-1].x, dPoints[dPoints.length-1].y);
			for (i = 0; i < dPoints.length; i++) {
			    shape.graphics.lineTo(dPoints[i].x, dPoints[i].y);
			}

			shape.graphics.lineStyle(1.5, (0x10000 * 0xee * int(side)) + (0x100 * 0xee) + (0xee-0xee * int(side)), .05);
			for (i = 0; i < dPoints.length; i++) {
				shape.graphics.drawCircle(dPoints[i].x, dPoints[i].y,4);
			}
			for (i = 0; i < m_Points.length; i++) {
				shape.graphics.drawCircle(m_Points[i].x, m_Points[i].y,1);
			}
				
		}
		
		function getLine(p1:Point,p2:Point):Point	//直線 y=[ts.x]x+[ts.y]を返す
		{
			var vx=p1.x-p2.x;
			var vy=p1.y-p2.y;
			var ts=new Point();
			ts.x=vy/vx;
			ts.y=p2.y-ts.x*p2.x;
			return ts;
		}
		
		function getCrossLine(p1:Point,p2:Point,p3:Point):Point	//点p1-p2に直交し、p3を通る直線 y=[ts.x]x+[ts.y]を返す
		{
			var vx=p1.x-p2.x;
			var vy=p1.y-p2.y;
			var ts=new Point();
			ts.x=-vx/vy;
			ts.y=p3.y-ts.x*p3.x;
			return ts;
		}
		
		function getCrossPoint2Lines(l1a:Number,l1b:Number,l2a:Number,l2b:Number):Point	//y=[l1a]x+[l1b],y=[l2a]x+[l2b]の交点を返す
		{
			var x = (l2b - l1b) / (l1a - l2a);
			return new Point(x, l1a * x + l1b);
		}
		
		
	}