很多时候一个多边形外观或圆形外观很难模拟复杂的事物
比如模拟一个鱼缸可能就需要拼接多个外观(b2Fixture)对象
box2d中的用法一个刚体可以绑定多个外观来进行模拟
需要注意的是跟据顶点坐标构建多边形时,都是按顺时针
package { import Box2D.Collision.b2WorldManifold; import Box2D.Collision.Shapes.b2CircleShape; import Box2D.Collision.Shapes.b2PolygonShape; import Box2D.Common.Math.b2Vec2; import Box2D.Dynamics.b2Body; import Box2D.Dynamics.b2BodyDef; import Box2D.Dynamics.b2DebugDraw; import Box2D.Dynamics.b2Fixture; import Box2D.Dynamics.b2FixtureDef; import Box2D.Dynamics.b2World; import comingx.Ball; import flash.display.Bitmap; import flash.display.Sprite; import flash.events.Event; import flash.system.IMEConversionMode; /** * ... * @author My_style */ [SWF(width="600",height="480",frameRate="30")] public class Main extends Sprite { [Embed(source = "./assets/container.png")] private var ContainerImg:Class; private const PIXEL_TO_METER:int = 30; private var world:b2World; private var containerBody:b2Body; public function Main():void { var c:Bitmap = new ContainerImg(); addChild(c); c.x = stage.stageWidth / 2-c.width/2; c.y = stage.stageHeight / 2-c.height/2; creatWorld(); creatBall(); creatContainer(); // creatDebugDraw(); addEventListener(Event.ENTER_FRAME, render); } private function creatWorld():void { var gravity:b2Vec2 = new b2Vec2(0, 10); world = new b2World(gravity, true); world.SetWarmStarting(true);//刚体初始化的时候不受重力影响 } private function creatContainer():void { var coords:Array=[ [[61,55],[77,67],[39,135],[23,124]], [[23,124],[39,135],[25,220],[6,218]], [[6,218],[25,220],[44,305],[28,312]], [[28,312],[44,305],[94,372],[82,384]], [[82,384],[94,372],[167,413],[161,425]], [[161,425],[167,413],[250,424],[250,437]], [[250,438],[250,424],[339,416],[341,429]], [[341,430],[339,416],[411,383],[418,393]], [[418,393],[411,383],[464,327],[478,334]], [[478,334],[464,327],[489,254],[504,252]], [[504,252],[489,254],[488,183],[504,177]], [[504,177],[488,183],[470,112],[488,103]], [[488,103],[470,112],[443,66],[465,63]], [[77,67],[72,46],[436,43],[443,66]] ]; var containerBodyDef:b2BodyDef = new b2BodyDef(); containerBodyDef.type = b2Body.b2_staticBody; containerBodyDef.position.Set(40 / PIXEL_TO_METER, 20 / PIXEL_TO_METER); containerBody = world.CreateBody(containerBodyDef); creatFixtures(coords); } private function creatFixtures(coords:Array):void { for (var i:int = 0; i < coords.length; i++ ){ var polygonShape:b2PolygonShape = new b2PolygonShape(); var shapeVertices:Array = creatVerticesArray(coords[i]); polygonShape.SetAsArray(shapeVertices); var fixtureDef:b2FixtureDef = new b2FixtureDef(); fixtureDef.density = 1.0; fixtureDef.friction = 0.5; fixtureDef.restitution = 1.0; fixtureDef.shape = polygonShape; containerBody.CreateFixture(fixtureDef); } } private function creatVerticesArray(coords:Array):Array { if (coords.length < 3) { throw new Error("初始化顶点错误"); } var verticeArray:Array = new Array(); for (var i:int = 0; i < coords.length; i++ ) { var vertice:b2Vec2 = new b2Vec2(); vertice.Set(coords[i][0]/PIXEL_TO_METER, coords[i][1]/PIXEL_TO_METER); verticeArray.push(vertice); } return verticeArray; } private function creatBall():void { for (var i:int = 0; i < 10; i++ ){ var ballDef:b2BodyDef = new b2BodyDef(); ballDef.type = b2Body.b2_dynamicBody; ballDef.position.Set(stage.stageWidth / 2 / PIXEL_TO_METER, 100 / PIXEL_TO_METER); var r:Number = Math.random() * 10 + 10; var ballShape :b2CircleShape = new b2CircleShape(r/PIXEL_TO_METER); var fixtureDef:b2FixtureDef = new b2FixtureDef(); fixtureDef.shape = ballShape; fixtureDef.density = 1.0; fixtureDef.friction = 0.8; fixtureDef.restitution = 1; var ballSprite:Sprite = new Ball(r, i + ""); addChild(ballSprite); ballDef.userData = ballSprite; var ballbody:b2Body = world.CreateBody(ballDef); ballbody.CreateFixture(fixtureDef); } } private function synchorBallSprite():void { var body:b2Body = world.GetBodyList(); while (body) { if (body.GetDefinition().userData is Ball) { var ballSprite:Ball = body.GetDefinition().userData as Ball; ballSprite.x = body.GetTransform().position.x * PIXEL_TO_METER; ballSprite.y = body.GetTransform().position.y * PIXEL_TO_METER; ballSprite.rotation = body.GetTransform().GetAngle() * 180 / Math.PI; } body = body.GetNext(); } } private function creatDebugDraw():void { var debugSprite:Sprite = new Sprite(); addChild(debugSprite); var debug:b2DebugDraw = new b2DebugDraw(); debug.SetSprite(debugSprite); debug.SetLineThickness(1); debug.SetAlpha(1); debug.SetFillAlpha(.8); debug.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit); debug.SetDrawScale(PIXEL_TO_METER); world.SetDebugDraw(debug); } private function render(e:Event):void { var timeStep:Number = 1 / 30; var interation:int = 10; synchorBallSprite(); world.Step(timeStep, interation, interation); world.ClearForces(); //world.DrawDebugData(); } } }