Box2D C++ 教程-物体
2014-03-11 21:48
253 查看
Box2D C++ 教程-物体
物体(Bodies)物体是物理场景中的基本对象,但是这里的物体并不是你看到的实际互相弹跳碰撞的实物。听起来很费解吗?挺住!马上做解释!
http://ohcoder.com/blog/2012/11/29/bodies/
你可以把物体想象成是一种看不见摸不着的实物的属性。这些不可见的属性是:
-质量(mass)-实物到底有多重
-速度(velocity)-某方向上实物到底运动多快
-转动惯量(rotational inertia)-开始或停止转动需要多大的力
-角速度(angular velocity)-某方向实物转动的速度有多快
-位置(location)-实物在哪
-角度(angle)-实物面向哪个方向
即便你知道一个对象的所有这些特性,你仍然不清楚这个对象的长像或者它与其它物体产生碰撞的时候会作出什么样的反应。我们需要使用定制器(fixtures)来定义物体的形状和大小,关于定制器我们会在本教程的下一个话题进行讲解。目前我们还是使用一个简单的盒子来代替随后出现的定制器(fixture)的及其细节。让我们创建一个物体并为它设置一些基本属性,来看看是如何工作的吧。
有三种类型的物体:静态物体(static),动态物体(dynamic)以及运动学物体(kinematic)。前两个顾名思义看起来更好理解一些。最后一个看起来理解起来并不是那么的直观。目前先忽略一些细节,随后再进行解释。首先我们将创建一个动态物体,我们可以在场景中的地面上让其进行移动,然后试着设置速度,等等。让我们开始吧。
创建物体
物体的创建由一些定义组成,通过这些定义来创建物体自身。如果你想创建多个相同或相似的物体,这种方式比较方便(译者注:这里所说的创建物体的定义就是下面代码中的b2BodyDef结构体的定义,以后所创建的物体都可以根据这个结构体做快速初始化)。在Footest类的构造方法里,添加如下代码,来创建物体定义:
1 2 3 4 | [code]b2BodyDef myBodyDef; myBodyDef.type = b2_dynamicBody; //this will be a dynamic body myBodyDef.position.Set(0, 20); //set the starting position myBodyDef.angle = 0; //set the starting angle |
1 | [code]b2Body* dynamicBody = m_world->CreateBody(&myBodyDef); |
of Masses)”选项,最多你可以看到物体下落的位置)。
为物体设置大小,形状以及其它更明确的性质,通过为其添加定制器(fixtures)来实现。此外,即便为物体添加默认的定制器也会影响物体的质量。物体可以附加多个定制器,附加的每一个定制器都会影响物体的总质量。目前,我们只为物体添加一个简单的定制器,一个四方形,定制器本来是下一次教程的话题,现在细说有点早。
1 2 3 45 | [code]b2PolygonShape boxShape; boxShape.SetAsBox(1,1); b2FixtureDef boxFixtureDef; boxFixtureDef.shape = &boxShape; boxFixtureDef.density = 1; dynamicBody->CreateFixture(&boxFixtureDef); |
现在,当你运行程序,会看到一个下落的小盒子。如果你足够快,你可以用鼠标捕捉它,然后随意拖拽,如果小盒子丢出屏幕范围可以按restart按钮(R键)重新开始。既然这是个动态物体,那么它可以移动并且旋转,并受到重力的影响。
设置物体属性
现在,我们设置一些文章开始提到的属性,看看会发生什么。比如说,改变初始位置和角度:
1 | [code]dynamicBody->SetTransform( b2Vec2( 10, 20 ), 1 ); |
12 | [code]#define DEGTORAD 0.0174532925199432957f #define RADTODEG 57.295779513082320876f dynamicBody->SetTransform(b2Vec2(10, 20), 45 * DEGTORAD ); //45 degrees counter-clockwise |
12 | [code]dynamicBody->SetLinearVelocity(b2Vec2( -5, 5 ));//moving up and left 5 units per second dynamicBody->SetAngularVelocity(-90 * DEGTORAD);//90 degrees per second clockwise |
现在让我们看看什么是静态物体。既然我们对物体已经有了一些定义和一个定制器,那我们就重用它们,只修改一些必须的特性:
1 2 3 4 | [code]myBodyDef.type = b2_staticBody; //this will be a static body myBodyDef.position.Set(0, 10); //slightly lower position b2Body* staticBody = m_world->CreateBody(&myBodyDef); //add body to world staticBody->CreateFixture(&boxFixtureDef); //add fixture to body |
运动学物体(Kinematic bodies)
最后,让我们来看看有关于运动学物体的部分。正如我们之前看到的动态物体可以移动,但静态物体不能移动。当一个静态物体和动态物体发生碰撞的时候,静态物体总能“获胜”并坚挺在地面上,动态物体根据实际情况被弹回,两个物体之间不会发生重叠。运动学物体非常像静态物体,当它与动态物体相撞之后,总能保持自己不动,把动态物体反弹回去,与静态物体唯一不同的是,运动学物体可以被移动。
可以像下面这样创建一个运动学物体:
1 2 3 45 | [code]myBodyDef.type = b2_kinematicBody;//this will be a kinematic body myBodyDef.position.Set(-18, 11); //start from left side,slightly above the static body b2Body* kinematicBody = m_world->CreateBody(&myBodyDef); //add body to world kinematicBody->CreateFixture(&boxFixtureDef); //add fixture to body kinematicBody->SetLinearVelocity( b2Vec2( 1, 0 ) );//move right 1 unit per second kinematicBody->SetAngularVelocity( 360 * DEGTORAD );//1 turn per second counter-clockwise |
新创建的物体在场景中可以被移动或者旋转,但不会被重力所影响,并且当与动态物体发生碰撞的时候也不会受到影响。注意当它与静态物体发生接触的时候,它们之间是没有相互作用的。
在大多数游戏中,动态物体通常被用来创建玩家和其它场景中的角色,静态物体被用来创建墙,地板等等。运动学物体通常用来扮演那些可以移动或旋转但是不能被动态物体所撞动的物体。一个比较恰当的例子是横屏游戏中一个移动的平台,该平台可以使用运动学物体来模拟-这可以保证不论玩家如何跳跃,都不能与之由于相撞而产生位移。
获取物体属性(Getting body properties)
很多情况下你都想知道物体目前在哪儿或者移动有多快,旋转角度等等。实现这个很简单,让我们现在就做一个尝试。为此,我们需要在Step()方法中访问物体变量,所以我们需要声明一个类的成员变量来代替只在构造函数中声明的变量。
12 | [code]//in the class itself, not inside the constructor! b2Body* dynamicBody; |
1 2 3 45 | [code]b2Vec2 pos = dynamicBody->GetPosition(); float angle = dynamicBody->GetAngle(); b2Vec2 vel = dynamicBody->GetLinearVelocity(); float angularVel = dynamicBody->GetAngularVelocity(); m_debugDraw.DrawString(5, m_textLine,"Position:%.3f,%.3f Angle:%.3f", pos.x, pos.y, angle * RADTODEG); m_textLine += 15; m_debugDraw.DrawString(5, m_textLine, "Velocity:%.3f,%.3f Angular velocity:%.3f", vel.x, vel.y, angularVel * RADTODEG); m_textLine += 15; |
你可以通过GetPositon()和GetAngle()方法返回SetTransform所设置的值,而且不会发生值的改变。比如说,像下面这行代码根本不会引起物体位置的移动。
1 | [code]body->SetTransform( body->GetPosition(), body->GetAngle() ); |
遍历世界中的物体
如果你想监视世界中的所有物体,你可以像下面这样做。GetBodyList()方法可以返回物体链表的第一个元素。
1 2 3 4 | [code]for ( b2Body* b = m_world->GetBodyList(); b; b = b->GetNext()) { //do something with the body 'b' } |
当一个物体完成了它的使命,你可以通过调用世界对象的DestroyBody方法将其移除:
1 | [code]m_world->DestroyBody(dynamicBody); |
相关文章推荐
- Box2D C++ 教程-物体
- Box2D C++ 教程-物体
- Box2D C++ 教程-安全地移除物体
- Box2D C++ 教程 第五节:物体(Bodies)
- Box2D C++教程14-自己绘制物体
- Box2D C++教程5-物体(Bodies)
- Box2D C++教程10-匀速运动
- Box2D C++ 教程-碰撞过滤
- Box2D C++ 教程-环境设置
- Box2D C++教程6-定制器(Fixtures)
- Box2D C++ 教程-Testbed结构
- Box2D C++ 教程-定制器
- Box2D C++ 教程 第二节:环境设置
- Box2D C++教程-设置世界(World)7
- Box2D C++ 教程-创建测试
- Box2D C++ 教程-设置世界
- Box2D C++ 教程-用户数据
- Box2D C++ 教程-使用debug Draw
- Box2D C++ 物体的安全删除
- Box2D C++教程13-使用debug draw