/**
* Copyright lizhi ( http://wonderfl.net/user/lizhi )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/8iPN
*/
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Vector3D;
/**
* ...
* @author lizhi
*/
public class CollisionTest extends Sprite
{
private var bodys:Vector.<Body> =new Vector.<Body>;
private var myC:Circle;
private var collisions:Object = { };
public function CollisionTest()
{
collisions[Body.TYPE_CIRCLE+":" + Body.TYPE_CIRCLE] = circleCircle;
collisions[Body.TYPE_LINE+":" + Body.TYPE_CIRCLE] = lineCircle
collisions[Body.TYPE_CIRCLE+":" + Body.TYPE_LINE] = circleLine;
collisions[Body.TYPE_LINE+":" + Body.TYPE_LINE] = lineLine;
collisions[Body.TYPE_POLYGON+":" + Body.TYPE_POLYGON] = polygonPolygon;
addEventListener(Event.ENTER_FRAME, enterFrame);
for (var i:int = 0; i < 3;i++ ) {
var l:Line = new Line;
l.a.x = 400 * Math.random();
l.a.y = 400 * Math.random();
l.b.x = 400 * Math.random();
l.b.y = 400 * Math.random();
bodys.push(l);
}
for (i = 0; i < 5;i++ ) {
var c:Circle = new Circle;
c.a.x = 400 * Math.random();
c.a.y = 400 * Math.random();
c.radius =10+ 50 * Math.random();
bodys.push(c);
}
for (i = 0; i < 5;i++ ) {
var p:Polygon = new Polygon;
var n:int = 3 + Math.random() * 3;
var start:Number = Math.PI * Math.random();
var cen:Vector3D = new Vector3D(400 * Math.random(), 400 * Math.random());
var r:Number = 20 + 50 * Math.random();
for (var j:int = 0; j < n;j++ ) {
var v:Vector3D = new Vector3D;
var a:Number = start + j*Math.PI * 2 / n;
v.x = cen.x + r * Math.cos(a);
v.y = cen.y + r * Math.sin(a);
p.vertexs.push(v);
}
bodys.push(p);
}
myC = c;
}
private function enterFrame(e:Event):void
{
graphics.clear();
myC.a.x = mouseX;
myC.a.y = mouseY;
for (var i:int = 0; i < bodys.length;i++ ) {
var a:Body = bodys[i];
graphics.lineStyle(0);
if (a is Line) {
var l:Line = a as Line;
graphics.moveTo(l.a.x, l.a.y);
graphics.lineTo(l.b.x, l.b.y);
}else if (a is Circle) {
var c:Circle = a as Circle;
graphics.drawCircle(c.a.x, c.a.y, c.radius);
}else if (a is Polygon) {
var p:Polygon = a as Polygon;
var first:Vector3D = null;
for each(var v:Vector3D in p.vertexs) {
if (first==null) {
graphics.moveTo(v.x, v.y);
first = v;
}else {
graphics.lineTo(v.x, v.y);
}
}
graphics.lineTo(first.x, first.y);
}
for (var j:int = i + 1; j < bodys.length; j++ ) {
var b:Body = bodys[j];
var fun:Function = collisions[a.type+":" + b.type];
if(fun!=null)
fun(a, b);
}
}
}
private function circleCircle(a:Circle, b:Circle):void
{
graphics.lineStyle(0,0xff0000);
if (Vector3D.distance(a.a, b.a)<(a.radius + b.radius) ) {
graphics.moveTo(a.a.x, a.a.y);
graphics.lineTo(b.a.x, b.a.y);
}
}
private function circleLine(a:Circle, b:Line):void
{
lineCircle(b, a);
}
private function lineCircle(a:Line, b:Circle):void
{
graphics.lineStyle(0,0xff00);
var ba:Vector3D = a.b.subtract(a.a);
var n:Vector3D = ba.clone();
n.normalize();
var v1:Vector3D = b.a.subtract(a.a);
var d:Number = n.dotProduct(v1);
var n2:Vector3D = n.clone();
n2.scaleBy(d);
var c:Vector3D = a.a.add(n2);
if(Vector3D.distance(c,b.a)>b.radius){
return;
}
var v2:Vector3D = b.a.subtract(a.b);
var w:Number = ba.length;
var d1:Number = v1.dotProduct(n);
n.negate();
var d2:Number = v2.dotProduct(n);
if (d1 < 0 || d2 < 0 || d1 > w || d2 > w) {
if (Vector3D.distance(a.a,b.a)<b.radius) {
graphics.moveTo(a.a.x, a.a.y);
graphics.lineTo(b.a.x, b.a.y);
}else if (Vector3D.distance(a.b,b.a)<b.radius) {
graphics.moveTo(a.b.x, a.b.y);
graphics.lineTo(b.a.x, b.a.y);
}
return;
}
graphics.moveTo(c.x, c.y);
graphics.lineTo(b.a.x, b.a.y);
}
private function lineLine(a:Line, b:Line):void
{
}
private function polygonPolygon(a:Polygon, b:Polygon):void
{
for each(var v:Vector3D in a.vertexs) {
pointPolygon(v, b);
}
for each(v in b.vertexs) {
pointPolygon(v, a);
}
}
private function pointPolygon(v:Vector3D, p:Polygon):void {
for (var i:int = 0; i < p.vertexs.length;i++ ) {
if (i==0) {
var a:Vector3D = p.vertexs[p.vertexs.length-1];
}else {
a = p.vertexs[i - 1];
}
var b:Vector3D = p.vertexs[i];
var n:Vector3D = b.subtract(a);
var l:Vector3D = v.subtract(a);
if (n.crossProduct(l).z<0) {
return;
}
}
graphics.lineStyle(0, 0xff00ff);
graphics.drawCircle(v.x, v.y, 2);
}
}
}
import flash.geom.Vector3D;
class Body {
public static var TYPE_CIRCLE:int = 1;
public static var TYPE_LINE:int = 2;
public static var TYPE_POLYGON:int = 3;
public var type:int;
}
class Circle extends Body
{
public var a:Vector3D = new Vector3D;
public var radius:Number = 100;
public function Circle()
{
type = Body.TYPE_CIRCLE;
}
}
class Line extends Body
{
public var a:Vector3D = new Vector3D;
public var b:Vector3D = new Vector3D;
public function Line()
{
type = Body.TYPE_LINE;
}
}
class Polygon extends Body{
public var vertexs:Vector.<Vector3D> = new Vector.<Vector3D>;
public function Polygon()
{
type = Body.TYPE_POLYGON;
}
}