Beautifl - Flash Gallery

Thumbnail : 方向一定しつつ衝突判定 forked from: Yawaraka Balls
方向一定しつつ衝突判定 forked from: Yawaraka Balls
HaraMakoto 2009-11-18 MIT License

再生するにはFlash Playerが必要です。デスクトップのブラウザでご覧ください。

package
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	
	import net.hires.debug.Stats;
	
	[SWF(width="465", height="465", backgroundColor="#000000", frameRate=60)]
	public class HitTest3 extends Sprite
	{
		private var elemList:Array = new Array();
		private var elemNum:int = 20;
		private var colManager:EasyColosionManager = new EasyColosionManager();
		private var RoadList:Array = new Array();
		
		public function HitTest3()
		{
			super();
			addChild(new Stats());
			init();
			addEventListener(Event.ENTER_FRAME, handleEnterFrame);
		}
		
		private function init():void {
			//道路一覧
			RoadList = [
				new RoadUnit(80,445,"y",-1),new RoadUnit(140,20,"y",1),
				new RoadUnit(200,445,"y",-1),new RoadUnit(240,20,"y",1),
				new RoadUnit(340,445,"y",-1),new RoadUnit(400,20,"y",1),
				new RoadUnit(445,90,"x",-1),new RoadUnit(20,140,"x",1),
				new RoadUnit(445,180,"x",-1),new RoadUnit(20,210,"x",1),
				new RoadUnit(445,280,"x",-1),new RoadUnit(20,340,"x",1)
			]
			var i:int;
			for(i=0; i<elemNum; i++) {
				var elem:Elemet = new Elemet();
				addChild(elem);
				colManager.addElement(elem); //衝突マネージャ
				elemList.push(elem);
				var ru:RoadUnit = RoadList[int(RoadList.length*Math.random())];
				elem.px = ru.x;
				elem.py = ru.y;
				if(ru.vecType=="x") {
					if(ru.posinega==1) {
						elem.px += 100*Math.random();
					} else {
						elem.px -= 100*Math.random();
					}
				} else {
					elem.py += 100*Math.random();					
				}
				elem.init((ru.vecType=="x"),(ru.vecType=="y"),0.01*ru.posinega, 0.01*ru.posinega,ru.x, ru.y);
			}
//			var too:TooSenBoo = new TooSenBoo();
//			addChild(too);
//			colManager.addElement(too);
//			elemList.push(too);
//			elemNum++;
			
			this.graphics.clear();
			for(i=0; i<RoadList.length; i++) {
				var rr:RoadUnit = RoadList[i];
				this.graphics.lineStyle(1,0x333333);
				this.graphics.moveTo(rr.x,rr.y);
				var goalNum:Number = 465;
				if(rr.posinega==-1) goalNum = 0;
				if(rr.vecType=="x") {
					this.graphics.lineTo(goalNum, rr.y);
				} else {
					this.graphics.lineTo(rr.x, goalNum);					
				}
			}
		}
		
		
		private function handleEnterFrame(event:Event):void {
			for (var t:int = 0; t < 4; t++) {
				var i:int;
				for(i=0; i<elemNum; i++) {
					elemList[i].update();
				}
				colManager.checkColision();
			}
			for(i=0; i<elemNum; i++) {
				elemList[i].render();
			}
		}
		
	}
}
	import flash.events.EventDispatcher;
	import flash.display.Sprite;
	import flash.utils.Timer;
	import flash.events.TimerEvent;
	import flash.geom.Point;
	import caurina.transitions.Tweener;
	import caurina.transitions.Equations;
	

class EasyColosionManager extends EventDispatcher {
	private var elemList:Array = new Array();
	private var elemlen:int = 0;
	private var spring:Number = 0.2;
	private var bounce:Number = -0.5;
	private var gravity:Number = 0.1;
	public function EasyColosionManager() {
		
	}
	
	public function addElement(elem:Elemet):void {
		elemList.push(elem);
		elemlen = elemList.length;
	}
	
	public function checkColision():void {
		var i:int;
		for(i=0; i<elemlen-1; i++) {
			var elem0:Elemet = elemList[i];
			for(var j:int=i+1; j<elemlen; j++) {
				var elem1:Elemet = elemList[j];
				elem0.hitTest(elem1);
			}
		}
		
	}
	
	//2者間の距離を返す
	private function culcDistBetElems(mc1:Sprite, mc2:Sprite):Number {
		var pt1:Point = new Point(mc1.x, mc2.x);
		var pt2:Point = new Point(mc2.x, mc2.y);
		var dist:Number = Point.distance(pt1, pt2);
		return dist;
	}
	
}

class Elemet extends Sprite {
	public var px:Number = 0;
	public var py:Number = 0;
	public var vx:Number = 0;
	public var vy:Number = 0;
	public var maxX:Number = 465;
	public var maxY:Number = 465;
	public var started:Boolean = false;
	public var radious:Number = 10;
	private var spring:Number = 0.1;
	private var bounce:Number = -0.5;
	
	private var cx:Number = 0;
	private var cy:Number = 0;
	private var priority:int = 0;
	
	private var isXAddition:Boolean = false;
	private var isYAddition:Boolean = true;
	private var additionalVx:Number = 0.1;
	private var additionalVy:Number = 0.01;
	private var fixX:Number = 200;
	private var fixY:Number = 200;
	
	private var startPt:Point = new Point(0,0);
	private var startVx:Number, startVy:Number;
	
	private var timer:Timer = new Timer(1000);
	public function Elemet() {
		radious = 16 * Math.random();
		makeBody();
	}
	
	private function makeBody():void {
		this.graphics.beginFill(0xFFFFFF*Math.random());
		this.graphics.drawCircle(0,0,radious);
		this.graphics.endFill();
	}
	
	public function attacked():void {
		Tweener.addTween(this, {alpha:0, time:0.2, transition:Equations.easeOutInBounce});
		Tweener.addTween(this, {alpha:1, time:0.2, delay:0.2, transition:Equations.easeOutInBounce});
	}
	
	public function contact(contactX:Number, contactY:Number, _priority:int, force:Number):void {
		var tx:Number = contactX - px;
		var ty:Number = contactY - py;
		
		var angle:Number = Math.atan2(ty, tx);
		var length:Number = Math.sqrt(tx*tx+ty*ty);
		
		vx -= (1-length/radious)*0.5*Math.cos(angle);
		vy -= (1-length/radious)*0.5*Math.sin(angle);
		
		if(this.priority < _priority) {
			this.priority = _priority;
			cx = tx;
			cy = ty;
		}
	}
	public function hitTest(elm:Elemet):void {
		var dx:Number = elm.px - px;
		var dy:Number = elm.py - py;
		var distanceSquared:Number = dx*dx+dy*dy;
		var contactDistance:Number = radious + elm.radious;
		if(distanceSquared < contactDistance*contactDistance) {
			var tx:Number = linearTransform(radious, 0, contactDistance, px, elm.px);
			var ty:Number = linearTransform(radious, 0, contactDistance, py, elm.py);
			contact(tx, ty, 2, 0.5);
			elm.contact(tx, ty, 2, 0.5);
		}
	}
	private function linearTransform(n:Number, s0:Number, s1:Number, d0:Number, d1:Number):Number {
		return ( d0+(n-s0)*(d1-d0) / (s1-s0) );
	}
	
	
	public function update():void {
		cx = 0;
		cy = 0;
		priority = 0;
	
		px += vx;
		py += vy;
		
		if(px-radious<0) {
			setStartPosition();
		}
		if(px+radious>465) {
			setStartPosition();
		}
		if(py-radious<0) {
			setStartPosition();
		}
		
		//端までいったら戻る
		if(isContactWall())
			setStartPosition();
			
		mainAdditionalVec();
		vy *= 0.9796;
		vx *= 0.9796;
	}
	public function init(xAnable:Boolean=true, yAnable:Boolean=false, _vx:Number=0.001, _vy:Number=0.001, _x:Number=200, _y:Number=200):void {
		startPt.x = _x; startPt.y = _y;
		startVx = _vx; startVy = _vy;
		changeAction(xAnable,yAnable,_vx,_vy,_x,_y);
	}
	private function setStartPosition():void {
		px = startPt.x;
		py = startPt.y;
		vx = startVx;
		vy = startVy;
	}
	public function changeAction(xAnable:Boolean=true, yAnable:Boolean=false, _vx:Number=0.001, _vy:Number=0.001, _x:Number=200, _y:Number=200):void {
		isXAddition = xAnable;
		isYAddition = yAnable;
		additionalVx = _vx;
		additionalVy = _vy;
		fixX = _x;
		fixY = _y;
	}
	private function isContactWall():Boolean {
		var truth:Boolean = false;
		if(isXAddition){
			if(px-radious>maxX)
				truth = true;
		} else if(isYAddition) {
			if(py-radious>maxY)
				truth = true;
		}
		return truth;
	}
	private function mainAdditionalVec():void {
		if(isXAddition) {
			vx+=additionalVx;
			py = fixY;
		}
		if(isYAddition) {
			vy+=additionalVy;
			px = fixX;
		}
		
		
	}
	
	public function render():void {
		this.x = px;
		this.y = py;
	}
}

class TooSenBoo extends Elemet {
	public function TooSenBoo() {
		
	}
	public override function update():void {
		px = 400;
		py = 200;
	}
}

class RoadUnit {
	public var x:Number;
	public var y:Number;
	public var vecType:String = "x";
	public var posinega:int = 1;
	public function RoadUnit(_x:Number=0,_y:Number=0, _vec:String="x", _pn:int=1 ) {
		x = _x;
		y = _y;
		vecType = _vec;
		posinega = _pn;
	} 
}