您的位置:首页 > 其它

《Box2D for Flash Games》翻译 在世界里添加刚体(B)

2014-04-07 21:14 465 查看
http://blog.sina.com.cn/s/blog_441c62380101i1wz.html



2,在世界里添加刚体(B)

还剩下添加地板,把砖块改成动态刚体的,先来考虑一下玩偶,如果玩偶的形状非圆非方怎么办。玩偶是 Totem Destroyer 游戏的主角,我们不能只用一个盒子草草了事,这样会对不起游戏里的角色的。

我想玩偶的形状应该如下



这就是我想到的玩偶,我们要用 Box2D创建它。左手边是玩偶轮廓,右手边是填充好的玩偶。

你首先注意到的是,这个玩偶是由许多个刚体一起组成了一个复合刚体,记住Box2D只对凸多边形产生作用,跟那些单一盒子状的木条是不一样的。我们需要把所有的玩偶对象用同样的方法混合。

我们先从竖直的盒子开始, 在最后一个brick 方法后调用它。

public function Main() {

world=new b2World(new b2Vec2(0,5),true);

debugDraw();

brick(275,435,30,30);

brick(365,435,30,30);

brick(320,405,120,30);

brick(320,375,60,30);

brick(305,345,90,30);

brick(320,300,120,60);

idol(320,242);

addEventListener(Event.ENTER_FRAME,updateWorld);

}

我们在 idol 方法里创建玩偶:

private function idol(pX:Number,pY:Number):void {

var bodyDef:b2BodyDef=new b2BodyDef();

bodyDef.position.Set(pX/worldScale,pY/worldScale);

var polygonShape:b2PolygonShape=new b2PolygonShape();

polygonShape.SetAsBox(5/worldScale,20/worldScale);

var fixtureDef:b2FixtureDef=new b2FixtureDef();

fixtureDef.shape=polygonShape;

fixtureDef.density=1;

fixtureDef.restitution=0.4;

fixtureDef.friction=0.5;

var theIdol:b2Body=world.CreateBody(bodyDef);

theIdol.CreateFixture(fixtureDef);

}

现在已经创建了一个新的盒子状图形,和之前建立的木条是一样的。

测试影片将会看到玩偶的身子:



玩偶的第二部分是在身子底部叠上一个十字交叉,相交叉的部分是由两个盒子状组成的,只不过他们都逆时针的旋转45度。

Creating an oriented box shape

想要创建一个定向的盒子形状,我们使用一个跟SetAsBox 类似的方法b2PolygonShape,你也可以使用更高级的 SetAsOrientedBox 方法。

参数是盒子的全长和全宽,盒子的中心点,还要定义一个b2Vec2对象和旋转弧度。

1,根据上面所说的, idol 方法这样接着写下去:

var bW:Number=5/worldScale;

var bH:Number=20/worldScale;

var boxPos:b2Vec2=new b2Vec2(0,10/worldScale);

var boxAngle:Number=- Math.PI/4;

前两行定义了盒子的大小,第三行定义了位置,你或许有些疑问,玩偶的第一个盒子刚体的位置是(320,242),为什么玩偶的第二个盒子刚体在(0,10)位置,他不应该离第一个盒子更近一点吗?

这就是你要学习的神奇的复合对象,这里的位置不是绝对位置,而是相对于第一个盒子的相对位置。

所以这一行的意思是:第二个盒子会被放置在第一个盒子中心点下方一点点的地方。

最后一行指明弧度为逆时针45度。

2,根据这四个变量,你可以如下所示调用 SetAsOrientedBox 方法。

polygonShape.SetAsOrientedBox(bW,bH,boxPos,boxAngle);

3,然后更新 fixture
shape

fixtureDef.shape=polygonShape;

4,哈,好神奇,我们把 fixture 连接到现有的 theIdol 刚体上了。

theIdol.CreateFixture(fixtureDef);

5,把同样的部分应用到另外一个盒子上去,只需要改变 boxAngle变量:

boxAngle=Math.PI/4;

6,创建定向盒子,更新 fixture
shape,把它添加到theIdol 刚体。

polygonShape.SetAsOrientedBox(bW.bH,boxPos,boxAngle);

fixtureDef.shape=polygonShape;

theIdol.CreateFixture(fixtureDef);

7,最后,完整的idol 方法如下所示:

private function idol(pX:Number,pY:Number):void{

var bodyDef:b2BodyDef=new b2BodyDef();

bodyDef.position.Set(pX/worldScale,pY/worldScale);

var polygonShape:b2PolygonShape=new b2PolygonShape();

polygonShape.SetAsBox(5/worldScale,20/worldScale);

var fixtureDef:b2FixtureDef=new b2FixtureDef();

fixtureDef.shape=polygonShape;

fixtureDef.density=1;

fixtureDef.restitution=0.4;

fixtureDef.friction=0.5;

var theIdol:b2Body=world.CreateBody(bodyDef);

theIdol.CreateFixture(fixtureDef);

var bW:Number=5/worldScale;

var bH:Number=20/worldScale;

var boxPos:b2Vec2=new b2Vec2(0,10/worldScale);

var boxAngle:Number=-Math.PI/4;

polygonShape.SetAsOrientedBox(bW,bH,boxPos,boxAngle);

fixtureDef.shape=polygonShape;

theIdol.CreateFixture(fixtureDef);

boxAngle=Math.PI/4;

polygonShape.SetAsOrientedBox(bW,bH,boxPos,boxAngle);

fixtureDef.shape=polygonShape;

theIdol.CreateFixture(fixtureDef);

}

8,测试影片:





现在开始创建它的头部

这次,你自己独立完成吧,说到底他只是另一个定向盒子,这个玩偶对象的一部分,我会教你另外一种方法去解决这个问题,用一种特别厉害的方法去键多边形。

创建任意多边形

Box2D允许你创建任意多边形,只要这个多边形是多边形,也就是说所有的内角都小于180度,所以

所有的顶点都远离中心点,还有你提供的点要是顺时针方向。

1,首先新建一个 vector 来存储所有的向量:

var vertices:Vector.=new Vector.();

2,然后把所有的顶点以 b2Vec2 对象顺时针顺序放入数组,他们的位置是相对于人偶中心点的相对位置,

vertices.push(new b2Vec2(-15/worldScale,-25/worldScale));

vertices.push(new b2Vec2(0,-40/worldScale));

vertices.push(new b2Vec2(15/worldScale,-25/worldScale));

vertices.push(new b2Vec2(0,-10/worldScale));

3,上面的几行代码写的是玩偶头的部分的四个向量,现在把这些向量转化成多边形。

polygonShape.SetAsVector(vertices,4)

SetAsVector 方法把vector中的向量顺时针排成一个多变形,第二个参数是需要使用的顶点个数。

4,最后了,通常你需要更新 fixture
shape 并把它添加到theIdol刚体上:

fixtureDef.shape=polygonShape;

theIdol.CreateFixture(fixtureDef);

5,idol方法如下所示:

private function idol(pX:Number,pY:Number):void{

var bodyDef:b2BodyDef=new b2BodyDef();

bodyDef.position.Set(pX/worldScale,pY/worldScale);

var polygonShape:b2PolygonShape=new b2PolygonShape();

polygonShape.SetAsBox(5/worldScale,20/worldScale);

var fixtureDef:b2FixtureDef=new b2FixtureDef();

fixtureDef.shape=polygonShape;

fixtureDef.density=1;

fixtureDef.restitution=0.4;

fixtureDef.friction=0.5;

var theIdol:b2Body=world.CreateBody(bodyDef);

theIdol.CreateFixture(fixtureDef);

var bW:Number=5/worldScale;

var bH:Number=20/worldScale;

var boxPos:b2Vec2=new b2Vec2(0,10/worldScale);

var boxAngle:Number=-Math.PI/4;

polygonShape.SetAsOrientedBox(bW,bH,boxPos,boxAngle);

fixtureDef.shape=polygonShape;

theIdol.CreateFixture(fixtureDef);

boxAngle=Math.PI/4;

polygonShape.SetAsOrientedBox(bW,bH,boxPos,boxAngle);

fixtureDef.shape=polygonShape;

theIdol.CreateFixture(fixtureDef);

var vertices:Vector.=new Vector.();

vertices.push(new b2Vec2(-15/worldScale,

-25/worldScale));

vertices.push(new b2Vec2(0,-40/worldScale));

vertices.push(new b2Vec2(15/worldScale,

-25/worldScale));

vertices.push(new b2Vec2(0,-10/worldScale));

polygonShape.SetAsVector(vertices,4);

fixtureDef.shape=polygonShape;

theIdol.CreateFixture(fixtureDef);

}

6,测试影片,玩偶站在最上面的木条上:



7,现在你需要创建一个地板,一个静态的盒子(用 floor 方法表示):

public function Main() {

world=new b2World(new b2Vec2(0,5),true);

debugDraw();

brick(275,435,30,30);

brick(365,435,30,30);

brick(320,405,120,30);

brick(320,375,60,30);

brick(305,345,90,30);

brick(320,300,120,60);

idol(320,242);

floor();

addEventListener(Event.ENTER_FRAME,updateWorld);

}

8,floor 方法如下所示:

private function floor():void {

var bodyDef:b2BodyDef=new b2BodyDef();

bodyDef.position.Set(320/worldScale,465/worldScale);

var polygonShape:b2PolygonShape=new b2PolygonShape();

polygonShape.SetAsBox(320/worldScale,15/worldScale);

var fixtureDef:b2FixtureDef=new b2FixtureDef();

fixtureDef.shape=polygonShape;

fixtureDef.restitution=0.4;

fixtureDef.friction=0.5;

var theFloor:b2Body=world.CreateBody(bodyDef);

theFloor.CreateFixture(fixtureDef);

}

9,把木条转化成动态刚体,注释去掉:

private function

brick(pX:int,pY:int,w:Number,h:Number):void {

var bodyDef:b2BodyDef=new b2BodyDef();

bodyDef.position.Set(pX/worldScale,pY/worldScale);

bodyDef.type=b2Body.b2_dynamicBody;

var polygonShape:b2PolygonShape=new b2PolygonShape();

polygonShape.SetAsBox(w/2/worldScale,h/2/worldScale);

var fixtureDef:b2FixtureDef=new b2FixtureDef();

fixtureDef.shape=polygonShape;

fixtureDef.density=2;

fixtureDef.restitution=0.4;

fixtureDef.friction=0.5;

var theBrick:b2Body=world.CreateBody(bodyDef);

theBrick.CreateFixture(fixtureDef);

}

10,最后,把idol 也改成动态刚体:

private function idol(pX:Number,pY:Number):void {

var bodyDef:b2BodyDef=new b2BodyDef();

bodyDef.position.Set(pX/worldScale,pY/worldScale);

bodyDef.type=b2Body.b2_dynamicBody;

var polygonShape:b2PolygonShape=new b2PolygonShape();

polygonShape.SetAsBox(5/worldScale,20/worldScale);

var fixtureDef:b2FixtureDef=new b2FixtureDef();

fixtureDef.shape=polygonShape;

fixtureDef.density=1;

fixtureDef.restitution=0.4;

fixtureDef.friction=0.5;

var theIdol:b2Body=world.CreateBody(bodyDef);

theIdol.CreateFixture(fixtureDef);

var bW:Number=5/worldScale;

var bH:Number=20/worldScale;

var boxPos:b2Vec2=new b2Vec2(0,10/worldScale);

var boxAngle:Number=- Math.PI/4;

polygonShape.SetAsOrientedBox(bW,bH,boxPos,boxAngle);

fixtureDef.shape=polygonShape;

theIdol.CreateFixture(fixtureDef);

boxAngle=Math.PI/4;

polygonShape.SetAsOrientedBox(bW,bH,boxPos,boxAngle);

fixtureDef.shape=polygonShape;

theIdol.CreateFixture(fixtureDef);

var vertices:Vector.=new Vector.();

vertices.push(new b2Vec2(-15/worldScale,

-25/worldScale));

vertices.push(new b2Vec2(0,-40/worldScale));

vertices.push(new b2Vec2(15/worldScale,

-25/worldScale));

vertices.push(new b2Vec2(0,-10/worldScale));

polygonShape.SetAsVector(vertices,4);

fixtureDef.shape=polygonShape;

theIdol.CreateFixture(fixtureDef);

}

正如本章开始所说,你将会使用Box2d写一个真正的游戏,这才刚开始。


本章结束啦,下章再见。

总结

本章是这本书里重要的章节之一,如何创建刚体,怎样使用它们来设计游戏关卡,想要使用更多的Box2D刚体,我建议你创建更多关的 Totem
Destroye游戏或者像 Red Removeer ,Angry Bird游戏,言而总之,总而言之,就是处理各种形状啦。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: