[Actionscript3] 纯文本查看 复制代码
package {
import Box2D.Dynamics.*;
import Box2D.Collision.*;
import Box2D.Collision.Shapes.*;
import Box2D.Common.Math.*;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.events.Event;
public class Main extends Sprite {
private var world:b2World=new b2World(new b2Vec2(0,10),true);
private var worldScale:int=30;
private var debris:Sprite;
private var canvas:Sprite;
private var laserSegment:b2Segment;
private var drawing:Boolean=false;
private var affectedByLaser:Vector.<b2Body>;
private var entryPoint:Vector.<b2Vec2>;
public function Main() {
debugDraw();
addStuff();
debris = new Sprite();
addChild(debris);
canvas = new Sprite();
addChild(canvas);
addEventListener(Event.ENTER_FRAME, updateWorld);
stage.addEventListener(MouseEvent.MOUSE_DOWN,mousePressed);
stage.addEventListener(MouseEvent.MOUSE_MOVE,mouseMoved);
stage.addEventListener(MouseEvent.MOUSE_UP,mouseReleased);
}
private function mousePressed(e:MouseEvent):void {
drawing=true;
laserSegment=new b2Segment();
laserSegment.p1=new b2Vec2(mouseX/worldScale,mouseY/worldScale);
}
private function mouseMoved(e:MouseEvent):void {
if (drawing) {
canvas.graphics.clear();
canvas.graphics.lineStyle(1,0xff0000);
canvas.graphics.moveTo(laserSegment.p1.x*worldScale,laserSegment.p1.y*worldScale);
canvas.graphics.lineTo(mouseX,mouseY);
}
}
private function mouseReleased(e:MouseEvent):void {
drawing=false;
laserSegment.p2=new b2Vec2(mouseX/worldScale,mouseY/worldScale);
}
private function debugDraw():void {
var debugDraw:b2DebugDraw = new b2DebugDraw();
var debugSprite:Sprite = new Sprite();
addChild(debugSprite);
debugDraw.SetSprite(debugSprite);
debugDraw.SetDrawScale(worldScale);
debugDraw.SetFlags(b2DebugDraw.e_shapeBit|b2DebugDraw.e_jointBit);
debugDraw.SetFillAlpha(0.5);
world.SetDebugDraw(debugDraw);
}
private function addStuff():void {
var floorBody:b2BodyDef= new b2BodyDef();
floorBody.position.Set(11,29);
floorBody.userData=new Object();
var floorShape:b2PolygonShape = new b2PolygonShape();
floorShape.SetAsBox(40,15);
var floorFixture:b2FixtureDef = new b2FixtureDef();
floorFixture.shape=floorShape;
var worldFloor:b2Body=world.CreateBody(floorBody);
worldFloor.CreateFixture(floorFixture);
//
var squareBody:b2BodyDef= new b2BodyDef();
squareBody.position.Set(16,5);
var squareShape:b2PolygonShape = new b2PolygonShape();
squareShape.SetAsBox(2.5,2.5);
var squareFixture:b2FixtureDef = new b2FixtureDef();
squareFixture.shape=squareShape;
var worldSquare:b2Body=world.CreateBody(squareBody);
worldSquare.CreateFixture(squareFixture);
//
var circleVector:Vector.<b2Vec2>=new Vector.<b2Vec2>();
var circleSteps:int=12;
var circleRadius:Number=3;
for (var i:int=0; i<circleSteps; i++) {
circleVector.push(new b2Vec2(circleRadius*Math.cos(2*Math.PI/circleSteps*i),circleRadius*Math.sin(2*Math.PI/circleSteps*i)));
}
var circleBody:b2BodyDef= new b2BodyDef();
circleBody.position.Set(5,5);
var circleShape:b2PolygonShape = new b2PolygonShape();
circleShape.SetAsVector(circleVector,circleSteps);
var circleFixture:b2FixtureDef = new b2FixtureDef();
circleFixture.shape=circleShape;
var worldCircle:b2Body=world.CreateBody(circleBody);
worldCircle.CreateFixture(circleFixture);
}
private function updateWorld(e:Event):void {
world.Step(1/30,10,10);
world.ClearForces();
if (laserSegment&&! drawing) {
affectedByLaser=new Vector.<b2Body>();
entryPoint=new Vector.<b2Vec2>();
world.RayCast(laserFired,laserSegment.p1,laserSegment.p2);
world.RayCast(laserFired,laserSegment.p2,laserSegment.p1);
laserSegment=null;
}
for (var currentBody:b2Body=world.GetBodyList(); currentBody; currentBody=currentBody.GetNext()) {
if (currentBody.GetUserData()!=null) {
currentBody.GetUserData().x=currentBody.GetPosition().x*worldScale;
currentBody.GetUserData().y=currentBody.GetPosition().y*worldScale;
currentBody.GetUserData().rotation=currentBody.GetAngle()*180/Math.PI;
}
}
world.DrawDebugData();
}
private function laserFired(fixture:b2Fixture,point:b2Vec2,normal:b2Vec2,fraction:Number):Number {
var affectedBody:b2Body=fixture.GetBody();
var affectedPolygon:b2PolygonShape=fixture.GetShape() as b2PolygonShape;
var fixtureIndex:int=affectedByLaser.indexOf(affectedBody);
if (fixtureIndex==-1) {
affectedByLaser.push(affectedBody);
entryPoint.push(point);
} else {
var rayCenter:b2Vec2=new b2Vec2((point.x+entryPoint[fixtureIndex].x)/2,(point.y+entryPoint[fixtureIndex].y)/2);
var rayAngle:Number=Math.atan2(entryPoint[fixtureIndex].y-point.y,entryPoint[fixtureIndex].x-point.x);
var polyVertices:Vector.<b2Vec2>=affectedPolygon.GetVertices();
var newPolyVertices1:Vector.<b2Vec2>=new Vector.<b2Vec2>();
var newPolyVertices2:Vector.<b2Vec2>=new Vector.<b2Vec2>();
var currentPoly:int=0;
var cutPlaced1:Boolean=false;
var cutPlaced2:Boolean=false;
for (var i:int=0; i<polyVertices.length; i++) {
var worldPoint:b2Vec2=affectedBody.GetWorldPoint(polyVertices[i]);
var cutAngle:Number=Math.atan2(worldPoint.y-rayCenter.y,worldPoint.x-rayCenter.x)-rayAngle;
if (cutAngle<Math.PI*-1) {
cutAngle+=2*Math.PI;
}
if (cutAngle>0&&cutAngle<=Math.PI) {
if (currentPoly==2) {
cutPlaced1=true;
newPolyVertices1.push(point);
newPolyVertices1.push(entryPoint[fixtureIndex]);
}
newPolyVertices1.push(worldPoint);
currentPoly=1;
} else {
if (currentPoly==1) {
cutPlaced2=true;
newPolyVertices2.push(entryPoint[fixtureIndex]);
newPolyVertices2.push(point);
}
newPolyVertices2.push(worldPoint);
currentPoly=2;
}
}
if (! cutPlaced1) {
newPolyVertices1.push(point);
newPolyVertices1.push(entryPoint[fixtureIndex]);
}
if (! cutPlaced2) {
newPolyVertices2.push(entryPoint[fixtureIndex]);
newPolyVertices2.push(point);
}
createSlice(newPolyVertices1,newPolyVertices1.length);
createSlice(newPolyVertices2,newPolyVertices2.length);
if (affectedBody.GetUserData()!=null) {
debris.removeChild(affectedBody.GetUserData());
}
world.DestroyBody(affectedBody);
}
return 1;
}
private function findCentroid(vs:Vector.<b2Vec2>, count:uint):b2Vec2 {
var c:b2Vec2 = new b2Vec2();
var area:Number=0.0;
var p1X:Number=0.0;
var p1Y:Number=0.0;
var inv3:Number=1.0/3.0;
for (var i:int = 0; i < count; ++i) {
var p2:b2Vec2=vs[i];
var p3:b2Vec2=i+1<count?vs[int(i+1)]:vs[0];
var e1X:Number=p2.x-p1X;
var e1Y:Number=p2.y-p1Y;
var e2X:Number=p3.x-p1X;
var e2Y:Number=p3.y-p1Y;
var D:Number = (e1X * e2Y - e1Y * e2X);
var triangleArea:Number=0.5*D;
area+=triangleArea;
c.x += triangleArea * inv3 * (p1X + p2.x + p3.x);
c.y += triangleArea * inv3 * (p1Y + p2.y + p3.y);
}
c.x*=1.0/area;
c.y*=1.0/area;
return c;
}
private function createSlice(vertices:Vector.<b2Vec2>,numVertices:int):void {
var centre:b2Vec2=findCentroid(vertices,vertices.length);
var sliceBody:b2BodyDef=new b2BodyDef ;
sliceBody.position.Set(centre.x,centre.y);
sliceBody.type=b2Body.b2_dynamicBody;
sliceBody.userData=new Sprite ;
debris.addChild(sliceBody.userData);
sliceBody.userData.graphics.lineStyle(2,Math.random()*0xFFFFFF);
sliceBody.userData.graphics.beginFill(Math.random()*0xFFFFFF);
for (var i:int=0; i<numVertices; i++) {
vertices[i].Subtract(centre);
if (i==0) {
sliceBody.userData.graphics.moveTo(vertices[i].x*worldScale,vertices[i].y*worldScale);
} else {
sliceBody.userData.graphics.lineTo(vertices[i].x*worldScale,vertices[i].y*worldScale);
}
}
sliceBody.userData.graphics.lineTo(vertices[0].x*worldScale,vertices[0].y*worldScale);
sliceBody.userData.graphics.endFill();
var slicePoly:b2PolygonShape=new b2PolygonShape ;
slicePoly.SetAsVector(vertices,numVertices);
var sliceFixture:b2FixtureDef=new b2FixtureDef ;
sliceFixture.shape=slicePoly;
sliceFixture.density=1;
var worldSlice:b2Body=world.CreateBody(sliceBody);
worldSlice.CreateFixture(sliceFixture);
for (i=0; i<numVertices; i++) {
vertices[i].Add(centre);
}
}
}
}