瘸腿蛤蟆原创笔记,欢迎转载,转载请标明出处:
上篇回顾
本篇名言:烦恼使我受着极大的影响……我一年多没有收到月俸,我和穷困挣扎;我在我的忧患中十分孤独,而且我的忧患是多么多,比艺术使我操心得更厉害! [米开朗基罗]
前段时间蛤蟆出差北京去了,好在中秋节前回来了哈哈。
上篇中,蛤蟆学习了Box2d物理引擎中的Ray-cast代码解释,接下去蛤蟆继续学习其他的Box2d引擎的使用。这次我们使用Box2d物理引擎来学习物理掉落的情况。
理论介绍
本次的理论知识基本和上次RayCast一致,需要补充如下内容:
1. Body定义变量
结构体b2BodyDef,这个结构体是在b2Body.h头文件中定义的,结构体具体定义如下,有些是带默认变量的。
b2BodyDef()
{
userData=
NULL;
position.Set(0.0f,0.0f);
angle= 0.0f;
linearVelocity.Set(0.0f,0.0f);
angularVelocity= 0.0f;
linearDamping= 0.0f;
angularDamping= 0.0f;
allowSleep=
true;
awake=
true;
fixedRotation=
false;
bullet=
false;
type= b2_staticBody;
active=
true;
gravityScale= 1.0f;
}
该结构体的作用是,我们创建一个Body的是时候必须要有这个结构体当做参数,然后根据这个结构体的参数创建我们想要的Body。这次我们重点关注下其中的类型。
userData是用于存储应用程序自定义的数据的。
position.Set用于设置Body创建的初始位置。
Angle用于设置Body弧度。
linearVelocity.Set用于设置Body的线速度,默认为0.
angularVelocity用于设置角速度
linearDamping线性阻尼用于减少线性速度,这个值可以设置大于1,但是大于 1 会 导致 阻尼效果会对时间步比较敏感。
angularDamping角速度阻尼用于减少角速度,这个值也不能设置太大,太大会导致 阻尼效果对时间步敏感。
allowSleep 默认是TRUE的,标注Body是否可以睡眠,如果设置FALSE,那么会增加CPU使用率。
awake= true; 标注Body起始时候是否睡眠。
fixedRotation=
false; Body是否可以旋转,默认是FALSE,不能旋转。这个对角色比较有用。
bullet= false; 这个用于标记是否是快速移动的Body。如果是快速移动的Body,则标记为 True,可以防止穿透其他移动的Body. 这个只能对运动的Body设置,不够会增加CPU处理时间。
type= b2_staticBody; type默认是 值是0,就是静态的Body,静态的BODY没有质量,也没有速度,只能通过手动移动。 值 1 ,则是运动的Body, 没有质量,但是有非零的速度(可以被程序员设置),通过解析器来实现移动。值 2 表示 动态的Body,有一个非负的质量,非零的速度(确定于外力),也通过解析器来实现运动。它是个枚举类型,如下表示。
enum
b2BodyType
{
b2_staticBody = 0,
b2_kinematicBody,
b2_dynamicBody
};
active= true; 标记是否是active.
gravityScale= 1.0f; Body的重力放大系数。
2. Fixture定义
Fixture定义是用来创建Fixture的,定义如下:
b2FixtureDef()
{
shape=
NULL;
userData=
NULL;
friction= 0.2f;
restitution= 0.0f;
density= 0.0f;
isSensor=
false;
b2Filter filter;
}
Shape必须被设置,这个shape会被复制,所以之前的shape变量可以被其他使用。
userData用来存储应用程序的特定数据
friction指定摩擦力,通常0到1
restitution指定回复力。通常0到1
Density 表示密度
isSensor表示是否是传感器,如果是传感器,那么会收集信息但是不会对碰撞产生反应。
Filter过滤接触的DATA
具体步骤
我们接着使用上次学习的模板,大家可以在 http://download.csdn.net/detail/notbaron/7871237
中下载这段代码。
1、修改RayCastNew的构造函数如下
RayCastNew()
{
b2Vec2 gravity;
gravity.Set(0.0f,-10.0f);
m_world=
new b2World(gravity);
b2Body** bodies = (b2Body**)b2Alloc(3 *
sizeof(b2Body*));
{
b2BodyDef bd;
bd.type=
b2BodyType(0);
bd.position.Set(2.587699890136719e-02f,5.515012264251709e+00f);
bd.angle= 0.000000000000000e+00f;
bd.linearVelocity.Set(0.000000000000000e+00f,0.000000000000000e+00f);
bd.angularVelocity= 0.000000000000000e+00f;
bd.linearDamping= 0.000000000000000e+00f;
bd.angularDamping= 0.000000000000000e+00f;
bd.allowSleep=
bool(4);
bd.awake=
bool(2);
bd.fixedRotation=
bool(0);
bd.bullet=
bool(0);
bd.active=
bool(32);
bd.gravityScale= 1.000000000000000e+00f;
bodies[0]= m_world->CreateBody(&bd);
{
b2FixtureDef fd;
fd.friction= 2.000000029802322e-01f;
fd.restitution= 0.000000000000000e+00f;
fd.density= 1.000000000000000e+00f;
fd.isSensor=
bool(0);
fd.filter.categoryBits=
uint16(1);
fd.filter.maskBits=
uint16(65535);
fd.filter.groupIndex=
int16(0);
b2PolygonShape shape;
b2Vec2 vs[8];
vs[0].Set(7.733039855957031e-01f,-1.497260034084320e-01f);
vs[1].Set(-4.487270116806030e-01f,1.138330027461052e-01f);
vs[2].Set(-1.880589962005615e+00f,-1.365900039672852e-01f);
vs[3].Set(3.972740173339844e-01f,-3.897832870483398e+00f);
shape.Set(vs,4);
fd.shape= &shape;
bodies[0]->CreateFixture(&fd);
}
}
{
b2BodyDef bd;
bd.type=
b2BodyType(2);
bd.position.Set(-3.122138977050781e-02f,7.535382270812988e+00f);
bd.angle= -1.313644275069237e-02f;
bd.linearVelocity.Set(8.230687379837036e-01f,7.775862514972687e-02f);
bd.angularVelocity= 3.705333173274994e-02f;
bd.linearDamping= 0.000000000000000e+00f;
bd.angularDamping= 0.000000000000000e+00f;
bd.allowSleep=
bool(4);
bd.awake=
bool(2);
bd.fixedRotation=
bool(0);
bd.bullet=
bool(0);
bd.active=
bool(32);
bd.gravityScale= 1.000000000000000e+00f;
bodies[1]= m_world->CreateBody(&bd);
{
b2FixtureDef fd;
fd.friction= 5.000000000000000e-01f;
fd.restitution= 0.000000000000000e+00f;
fd.density= 5.000000000000000e+00f;
fd.isSensor=
bool(0);
fd.filter.categoryBits=
uint16(1);
fd.filter.maskBits=
uint16(65535);
fd.filter.groupIndex=
int16(0);
b2PolygonShape shape;
b2Vec2 vs[8];
vs[0].Set(3.473900079727173e+00f,-2.009889930486679e-01f);
vs[1].Set(3.457079887390137e+00f,3.694039955735207e-02f);
vs[2].Set(-3.116359949111938e+00f,2.348500071093440e-03f);
vs[3].Set(-3.109960079193115e+00f,-3.581250011920929e-01f);
vs[4].Set(-2.590820074081421e+00f,-5.472509860992432e-01f);
vs[5].Set(2.819370031356812e+00f,-5.402340292930603e-01f);
shape.Set(vs,6);
fd.shape= &shape;
bodies[1]->CreateFixture(&fd);
}
}
{
b2BodyDef bd;
bd.type=
b2BodyType(2);
bd.position.Set(-7.438077926635742e-01f,6.626811981201172e+00f);
bd.angle= -1.884713363647461e+01f;
bd.linearVelocity.Set(1.785794943571091e-01f,3.799796104431152e-07f);
bd.angularVelocity= -5.908820639888290e-06f;
bd.linearDamping= 0.000000000000000e+00f;
bd.angularDamping= 0.000000000000000e+00f;
bd.allowSleep=
bool(4);
bd.awake=
bool(2);
bd.fixedRotation=
bool(0);
bd.bullet=
bool(0);
bd.active=
bool(32);
bd.gravityScale= 1.000000000000000e+00f;
bodies[2]= m_world->CreateBody(&bd);
{
b2FixtureDef fd;
fd.friction= 9.499999880790710e-01f;
fd.restitution= 0.000000000000000e+00f;
fd.density= 1.000000000000000e+01f;
fd.isSensor=
bool(0);
fd.filter.categoryBits=
uint16(1);
fd.filter.maskBits=
uint16(65535);
fd.filter.groupIndex=
int16(-3);
b2PolygonShape shape;
b2Vec2 vs[8];
vs[0].Set(1.639146506786346e-01f,4.428443685173988e-02f);
vs[1].Set(-1.639146655797958e-01f,4.428443685173988e-02f);
vs[2].Set(-1.639146655797958e-01f,-4.428443312644958e-02f);
vs[3].Set(1.639146357774734e-01f,-4.428444057703018e-02f);
shape.Set(vs,4);
fd.shape= &shape;
bodies[2]->CreateFixture(&fd);
}
}
GLESDebugDraw * _debugDraw =new
GLESDebugDraw(1.5); m_world->SetDebugDraw(_debugDraw);
uint32 flags = 0;
flags+=b2Draw::e_shapeBit;
_debugDraw->SetFlags(flags);
m_world->DrawDebugData();
b2Free(bodies);
bodies=
NULL;
}
2、修改Step函数如下
void Step(Settings*
settings )
{
float32 timeStep = settings->hz > 0.0f ? 1.0f /
settings->hz:
float32(0.0f);
m_world->Step(timeStep,settings->velocityIterations,
settings->positionIterations);
m_world->DrawDebugData();
}
编译运行如下:
代码解释
这里蛤蟆主要解释两个主要函数,也是主要区别于Ray-Cast的地方,一个是RayCastNew()
构造函数,一个是Step函数。代码总体上不是很复杂,就是在RayCastNew() 函数中构造了3个Body,然后Step函数会被每帧调用。让我们来具体看下这两个函数吧。
RayCastNew()
{
b2Vec2 gravity; //定义一个重力向量
gravity.Set(0.0f,-10.0f); //设置重力向量为 Y轴 负方向
m_world=
new b2World(gravity); //通过重力向量创建一个物理世界
b2Body** bodies = (b2Body**)b2Alloc(3 *
sizeof(b2Body*));//定义BODY数组,这里定义的比较有技巧,大家会照搬能看懂就可以
{
b2BodyDef bd; //定义第一个Body的定义变量
bd.type=
b2BodyType(0); //定义Body类型为静态Body
bd.position.Set(2.587699890136719e-02f,5.515012264251709e+00f); //定义第一个Body的位置
bd.angle= 0.000000000000000e+00f; //设置第一个Body角度
bd.linearVelocity.Set(0.000000000000000e+00f,0.000000000000000e+00f); //设置第一个Body线速度
bd.angularVelocity= 0.000000000000000e+00f; //设置第一个Body线角度
bd.linearDamping= 0.000000000000000e+00f; //设置第一个Body线性阻尼
bd.angularDamping= 0.000000000000000e+00f; //设置第一个Body角速度阻尼
bd.allowSleep=
bool(4); //设置第一个Body允许睡眠
bd.awake=
bool(2); //设置第一个Body会激活状态
bd.fixedRotation=
bool(0); //设置第一个Body不可转动
bd.bullet=
bool(0); //设置第一个Body不是快速移动Body
bd.active=
bool(32); //设置第一个Body启动激活
bd.gravityScale= 1.000000000000000e+00f; //设置第一个Body的重力放大系数
bodies[0]= m_world->CreateBody(&bd); //通过这个Body定义创建第一个Body
{
b2FixtureDef fd; //定义第一个Body的 Fixture 变量
fd.friction= 2.000000029802322e-01f; //定义第一个Body的摩擦力
fd.restitution= 0.000000000000000e+00f; //定义第一个Body的回复力
fd.density= 1.000000000000000e+00f; //定义第一个Body的密度
fd.isSensor=
bool(0); //设置第一个Body不是传感器。
fd.filter.categoryBits=
uint16(1);//碰撞目录位,通常设置一位
fd.filter.maskBits=
uint16(65535); //
fd.filter.groupIndex=
int16(0);// 这三个过滤蛤蟆试了下好像没什么作用
b2PolygonShape shape; //定义变量shape
b2Vec2 vs[8]; //定义坐标数组
vs[0].Set(7.733039855957031e-01f,-1.497260034084320e-01f); //第一个点
vs[1].Set(-4.487270116806030e-01f,1.138330027461052e-01f); //第二个点
vs[2].Set(-1.880589962005615e+00f,-1.365900039672852e-01f); //第三个点
vs[3].Set(3.972740173339844e-01f,-3.897832870483398e+00f); //第四个点
shape.Set(vs,4); //根据4个点,设置shape
fd.shape= &shape; //shape复制给fixture.
bodies[0]->CreateFixture(&fd); //将Fixture绑定到Body[0].
}
}
{
b2BodyDef bd; ////定义第二个Body的定义变量
bd.type=
b2BodyType(2); //定义Body类型为动态Body
bd.position.Set(-3.122138977050781e-02f,7.535382270812988e+00f); //设置第二个Body的位置
bd.angle= -1.313644275069237e-02f; //设置第二个Body角度
bd.linearVelocity.Set(8.230687379837036e-01f,7.775862514972687e-02f); //设置第二个Body线角度
bd.angularVelocity= 3.705333173274994e-02f; //设置第二个Body线角度
bd.linearDamping= 0.000000000000000e+00f; //设置第二个Body线性阻尼
bd.angularDamping= 0.000000000000000e+00f; //设置第二个Body角速度阻尼
bd.allowSleep=
bool(4); //设置第二个Body允许睡眠
bd.awake=
bool(2); //设置第二个Body会激活状态
bd.fixedRotation=
bool(0); //设置第二个Body不可转动
bd.bullet=
bool(0); //设置第二个Body不是快速移动Body
bd.active=
bool(32); //设置第二个Body启动激活
bd.gravityScale= 1.000000000000000e+00f; //设置第二个Body的重力放大系数
bodies[1]= m_world->CreateBody(&bd); //通过这个Body定义创建第二个Body
{
b2FixtureDef fd; //定义第二个Body的 Fixture 变量
fd.friction= 5.000000000000000e-01f; //定义第二个Body的摩擦力
fd.restitution= 0.000000000000000e+00f; //定义第二个Body的回复力
fd.density= 5.000000000000000e+00f; //定义第二个Body的密度
fd.isSensor=
bool(0); //设置第二个Body不是传感器。
fd.filter.categoryBits=
uint16(1);//碰撞目录位,通常设置一位
fd.filter.maskBits=
uint16(65535); //
fd.filter.groupIndex=
int16(0);//
b2PolygonShape shape; //定义变量shape
b2Vec2 vs[8]; //定义坐标数组
vs[0].Set(3.473900079727173e+00f,-2.009889930486679e-01f); //
vs[1].Set(3.457079887390137e+00f,3.694039955735207e-02f); //
vs[2].Set(-3.116359949111938e+00f,2.348500071093440e-03f); //
vs[3].Set(-3.109960079193115e+00f,-3.581250011920929e-01f); //
vs[4].Set(-2.590820074081421e+00f,-5.472509860992432e-01f); //
vs[5].Set(2.819370031356812e+00f,-5.402340292930603e-01f); //
shape.Set(vs,6); //根据6个点,设置shape
fd.shape= &shape; ////shape复制给fixture.
bodies[1]->CreateFixture(&fd); //将Fixture绑定到Body[1].
}
}
{
b2BodyDef bd; //定义第三个Body的定义变量
bd.type=
b2BodyType(2); //定义Body类型为动态Body
bd.position.Set(-7.438077926635742e-01f,6.626811981201172e+00f); //设置第三个Body的位置
bd.angle= -1.884713363647461e+01f; //设置第三个Body角度
bd.linearVelocity.Set(1.785794943571091e-01f,3.799796104431152e-07f); //设置第三个Body线角度
bd.angularVelocity= -5.908820639888290e-06f; //设置第三个Body线角度
bd.linearDamping= 0.000000000000000e+00f; //设置第三个Body线性阻尼
bd.angularDamping= 0.000000000000000e+00f; //设置第三个Body角速度阻尼
bd.allowSleep=
bool(4); //设置第三个Body允许睡眠
bd.awake=
bool(2); //设置第三个Body会激活状态
bd.fixedRotation=
bool(0); //设置第三个Body不可转动
bd.bullet=
bool(0); //设置第三个Body不是快速移动Body
bd.active=
bool(32); //设置第三个Body启动激活
bd.gravityScale= 1.000000000000000e+00f; //设置第三个Body的重力放大系数
bodies[2]= m_world->CreateBody(&bd); //通过这个Body定义创建第三个Body
{
b2FixtureDef fd; //定义第三个Body的 Fixture 变量
fd.friction= 9.499999880790710e-01f; //定义第三个Body的摩擦力
fd.restitution= 0.000000000000000e+00f; //定义第三个Body的回复力
fd.density= 1.000000000000000e+01f; //定义第三个Body的密度
fd.isSensor=
bool(0); //设置第三个Body不是传感器。
fd.filter.categoryBits=
uint16(1);//碰撞目录位,通常设置一位
fd.filter.maskBits=
uint16(65535); //碰撞掩码位,默认是0xFFFF(16进制位)
fd.filter.groupIndex=
int16(-3);//设置碰撞组,如果是负数就不会碰撞,如果是正数就会碰撞。如果为0,表示不是会发生碰撞的组。非零组优先级要高于碰撞掩码位。
b2PolygonShape shape; //定义变量shape
b2Vec2 vs[8]; //定义坐标数组
vs[0].Set(1.639146506786346e-01f,4.428443685173988e-02f); //
vs[1].Set(-1.639146655797958e-01f,4.428443685173988e-02f); //
vs[2].Set(-1.639146655797958e-01f,-4.428443312644958e-02f); //
vs[3].Set(1.639146357774734e-01f,-4.428444057703018e-02f); //
shape.Set(vs,4); //根据4个点,设置shape
fd.shape= &shape; //shape复制给fixture.
bodies[2]->CreateFixture(&fd); //将Fixture绑定到Body[2].
}
}
GLESDebugDraw * _debugDraw =new
GLESDebugDraw(1.5); //定义一个GLESDebugDraw
m_world->SetDebugDraw(_debugDraw); //注册GLESDebugDraw类负责画
uint32 flags = 0; //定义变量flags
flags+=b2Draw::e_shapeBit; //设置变量flasg,画shape.
_debugDraw->SetFlags(flags);//设置需要画的flags.
m_world->DrawDebugData();//画这3个Body
b2Free(bodies); //释放变量
bodies=
NULL; //赋值NULL
}
void Step(Settings*
settings )
{
float32 timeStep = settings->hz > 0.0f ? 1.0f /
settings->hz:
float32(0.0f); //定义一个帧频率变量
m_world->Step(timeStep,settings->velocityIterations,
settings->positionIterations); //调用Box2d源码中的Step函数。
m_world->DrawDebugData();//调用b2Draw类来画物理世界
}