box2d 绘制圆
在让刚体听我的——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();
}
}
}
|