在让刚体听我的——ApplyForce、ApplyImpulse、SetLinearVelocity一节中,来自天地会的sxl001问道如何创建圆形的边界(Round Boundary),好吧,我用这个教程来回答他。
实际上Box2D中没有专门创建圆弧的API (b2CircleDef创建的是实体圆形不是圆弧),所以试图寻找这样一个API的同学就放弃吧。结束了?坑爹啊!
哈哈,既然没有圆弧API,我就想其他的方法嘛。还记得Box2D多边形刚体的创建方法嘛?我们可以利用组合法,把多个形状组合起来形成一个这你的形状,当然也可以包括圆弧,下面的图可以更好的解释这一点。
图中我用12个线段组合起来模拟一个圆形,当然你可以用24个、36个线段等等。线段数越多,圆形就越标准,同时也越消耗CPU,所以能模拟出圆形效果就可以了,不用追求完美。现在,你应该有思路了吧:
- 定义线段的个数,12、24、36随你便,但不要太多。
- for循环遍历创建线段,根据线段索引i和圆形边界半径radius计算线段的坐标、角度
- 利用Box2D多边形刚体的组合法在线段的坐标位置创建与之角度相同的矩形刚体
效果如下,点击舞台任意位置,创建刚体:
我在下面的代码中做了详细的注释并highlight,我就不再讲解了,大家看代码吧!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | package { import Box2D.Collision.b2AABB; import Box2D.Collision.Shapes.b2CircleDef; import Box2D.Collision.Shapes.b2PolygonDef; import Box2D.Collision.Shapes.b2ShapeDef; import Box2D.Common.Math.b2Vec2; import Box2D.Dynamics.b2Body; import Box2D.Dynamics.b2BodyDef; import Box2D.Dynamics.b2DebugDraw; import Box2D.Dynamics.b2World; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; /** * http://www.ladeng6666.com * @author ladeng6666 */ publicclassMainextendsSprite { privatevarworld:b2World; privatevarbody:b2Body; publicfunctionMain() { //创建box2D世界 createWorld(); //创建box2D调试图 createDebug(); //创建刚体 createStuff(stage.stageWidth/2,0); //创建圆形边界 createCircleGround(); //侦听事件 addEventListener(Event.ENTER_FRAME,loop); stage.addEventListener(MouseEvent.MOUSE_DOWN,onStageMouseDown); } privatefunctiononStageMouseDown(e:MouseEvent):void { //在鼠标位置随机创建一个圆形或矩形刚体 createStuff(mouseX,mouseY,Math.random()>0.5); } privatefunctionloop(e:Event):void { world.Step(1/30,10); } privatefunctioncreateWorld():void { //1.创建一个环境 varenvironment:b2AABB=newb2AABB(); environment.lowerBound=newb2Vec2(-100,-100); environment.upperBound=newb2Vec2(100,100); //2.声明重力 vargravity:b2Vec2=newb2Vec2(0,10); //3.睡着的对象是否模拟 vardoSleep:Boolean=true; //4.创建b2World世界 world=newb2World(environment,gravity,doSleep); } privatefunctioncreateDebug():void { vardebugSprite:Sprite=newSprite(); addChild(debugSprite); vardebugDraw:b2DebugDraw=newb2DebugDraw(); debugDraw.m_sprite=debugSprite; debugDraw.m_drawScale=30.0; debugDraw.m_fillAlpha=0.5; debugDraw.m_lineThickness=1.0; debugDraw.m_drawFlags=b2DebugDraw.e_shapeBit|b2DebugDraw.e_jointBit; world.SetDebugDraw(debugDraw); } privatefunctioncreateStuff(posX:Number,posY:Number,isBox:Boolean=true):void { //1.创建刚体需求b2BodyDef varbodyRequest:b2BodyDef=newb2BodyDef(); bodyRequest.position.Set(posX/30,posY/30);//记得米和像素的转换关系 //2.Box2D世界工厂更具需求创建createBody()生产刚体 body=world.CreateBody(bodyRequest); //3.创建敢提形状需求b2ShapeDef的子类 if(isBox){ //创建矩形刚体形状需求 varshapeBoxRequest:b2PolygonDef=newb2PolygonDef(); shapeBoxRequest.density=3; shapeBoxRequest.friction=0.3; shapeBoxRequest.restitution=0.2; shapeBoxRequest.SetAsBox(1,1); body.CreateShape(shapeBoxRequest); }else{ //创建圆形刚体形状需求 varshapeCircleRequest:b2CircleDef=newb2CircleDef(); shapeCircleRequest.density=3; shapeCircleRequest.friction=0.3; shapeCircleRequest.restitution=0.2; shapeCircleRequest.radius=1; body.CreateShape(shapeCircleRequest); } body.SetMassFromShapes(); } privatefunctioncreateCircleGround():void { varcenterX:Number=stage.stageWidth/2; varcenterY:Number=stage.stageHeight/2; //1.创建刚体需求b2BodyDef varbodyRequest:b2BodyDef=newb2BodyDef(); bodyRequest.position.Set(centerX/30,centerY/30);//记得米和像素的转换关系 //2.Box2D世界工厂更具需求创建createBody()生产刚体 body=world.CreateBody(bodyRequest); //3.创建敢提形状需求b2ShapeDef的子类 //定义线段的个数 varsegmentNum:Number=36; //定义圆形边界的半径 varradius:Number=200; //根据半径和个数计算线段的长度 varsegmentlength:Number=radius *Math.sin(Math.PI/segmentNum); //for循环创建segmentNum个线段,合成圆形边界 for(vari:int=0;i<segmentNum;i++){ //定义形状需求 varshapeRequest:b2PolygonDef=newb2PolygonDef(); //形状的质量、摩擦系数、硬度 shapeRequest.density=0; shapeRequest.friction=0.3; shapeRequest.restitution=0.2; //计算每个线段的角度、坐标 varangle:Number=i/segmentNum *Math.PI*2; varbx:Number=radius *Math.cos(angle); varby:Number=radius *Math.sin(angle); //创建有方向的矩形刚体,合成总的圆形刚体 shapeRequest.SetAsOrientedBox(5/30,segmentlength/30,newb2Vec2(bx/30,by/30),angle); //4.b2Body刚体工厂根据需求createShape生产形状 body.CreateShape(shapeRequest); } body.SetMassFromShapes(); } } } |
源代码下载