您的位置:首页 > 编程语言 > Qt开发

给Qt装上物理引擎Box2D

2010-04-14 13:54 435 查看
前段时间在
CuteQt
上看到一篇
Qt+Box2D
的文章,又去
QtLab
看了下原文,感觉挺有意思的,就动手试了一下。
Box2D

1.0
版就之前的版本小小的改动了下
API
,那么下面,就让我简单的介绍下如何用
Box2D

Qt
上开发吧。

在这里,你可以找到:

Box2D 1.0
版在
Qt
中的使用简介

Box2D

Qt
是怎样联系到一起的

一些常见问题
Q&A

不同于之前网上的相关文章,我将用下面一个小
demo
来描述建立
Qt+Box2D
的过程,编译和使用的问题请看后面的
Q&A

Demo
描述:

我将用
Qt Graphics View Framework
模拟一个手机重力感应程序,这里并没有使用到重力感应相关的
API
,只是模拟一种手机转动时,重力感应的效果





图片中的手机外壳并不是模拟器,而是用贴图做的外壳效果,当通过程序转动手机时,里面的
item
会在模拟重力的作用下运动。而转动手机是通过
QgraphicsView

rotate
方法,且渲染开销较大。

一、

Box2D 1.0
版在
Qt
中的使用简介

1.0
版的
Box2D
在构建基础物理世界的方法上做了些许改变,下面根据常规的思路像大家介绍:

1.
创建一个用于
Box2D
仿真的世界,在
Box2D
里叫
b2World.
创建他需要定义重力,和另外一个用于模拟的
flag


// Define world, gravity

b2Vec2 gravity(0.0f,-10.0f);

bool doSleep = false;

world = new b2World(gravity, doSleep);

doSleep
的意思是,当所有仿真的物体(
body
)静止或离开
world
后,是否停

止对其的仿真。在这个
Demo
里,将其设为
false
,即物体静止后仍然仿真。

不然当物体静止后它就不会再动了。

关于
b2World
的创建,与前面版本不同的是,它不用自己定义
world
的大小

2.
构建各种
body
,包括
demo
里的各类图形
item
和将这些
item
框在手机屏幕内的对象

创建
body
需要先定义好另外三个用来描述或表示
body
性质的对象,
b2BodyDef

b2XXXShape

b2Fixture


XXX=Polygon

Circle
等在
Box2D
中定义的形状)

//upperBarBody

b2BodyDef upperBarBodyDef;

upperBarBodyDef.position.Set(93.0f, -0.5f);

b2Body *upperBarBody = world->CreateBody(&upperBarBodyDef);

b2PolygonShape upperBarBox;

upperBarBox.SetAsBox(93.0f, 0.5f);

upperBarBody->CreateFixture(&upperBarBox,0); //set density to zero for static
//body

以上是
static


body

,即静止的物体。下面是
dynamic

物体的定义:

// Create body with start-up position and rotation.

b2BodyDef bodyDef;

bodyDef.type = b2_dynamicBody;

//Take Care

bodyDef.position.Set(x(), -y());

bodyDef.angle = -(rotation() * (2 * PI)) / 360.0;

_body = _world->CreateBody(&bodyDef);

/*

const QPolygonF &poly = polygon();

int count = poly.size();

b2Vec2 vertices[count];

for (int i = 0; i < count; ++i) {

const QPointF &p = poly.at(i);

vertices[i].Set(p.x(), -p.y());

}*/

//

这里将与
Qt

交互的代码注释掉,用一般的构建方法

b2PolygonShape dynamicBox;

dynamicBox. SetAsBox(93.0f, 0.5f);

b2FixtureDef fixtureDef;

fixtureDef.shape = &dynamicBox;

fixtureDef.density = 600.0f; //wood 600kg/m^2

fixtureDef.friction = 0.5f;

fixtureDef.restitution = 0.5f; //0.0f~1.0f

_body->CreateFixture(&fixtureDef);

从上面的代码可以看出
static


dynamic

的物体,在对
b2Fixture

的要求上有所不同,而
Fixture

可以理解为物体附属的性质,比如:重力,摩擦力还有反弹力等

3.
进行仿真

上面的代码并没有开始仿真我们所建立的物理世界,只是定义好了世界里的对象,下面的代码告诉引擎,该怎样去模拟

world->Step(1.0f/30.0f, 10, 10);

…..

b2Vec2 position = _body->GetPosition();

float32 angle = _body->GetAngle();

以上只是关键的代码片段,
Step
是仿真的定义,
Step
第一个参数是每次仿真的时间间隔,后面两个参数,一个是速度增量,一个是位移增量。详细的介绍和使用注意最好还是看下
Box2D
的手册,涉及到一些物理知识。

后面的代码是处理每次仿真的函数里的,在
Qt
中,可以通过
QTimerEvent

QTimer
来处理每一步(
step
)的仿真,得到物体的位置和旋转,在通过
Qt
反映出来。

二、

Box2D

Qt
是怎样联系到一起的

前面基本上在说如何使用
Box2D
,下面介绍怎样在
Qt
中用。在
Qt

Box2D
只用作物理引擎,而真正的绘图还是交给
Qt
来做。还记得前面定义
body
时使用的
b2XXXShape
吗,关键就在这儿。


Polygon
图形为例,需要我们继承
QGraphicsPolygonItem
,在其中

const QPolygonF &poly = polygon();

int count = poly.size();

b2Vec2 vertices[count];

for (int i = 0; i < count; ++i) {

const QPointF &p = poly.at(i);

vertices[i].Set(p.x(), -p.y());

}

b2PolygonShape dynamicBox;

dynamicBox.Set(vertices, count);

而对于其他形状的物体,如
Circle


Rectangle

都可以找到对应的
Qt Graphics Item

。像比较复杂的图形,只要知道怎样得到
painterPath

,就可以做相应的处理,通过
vertice

定义我们的
Box2D body

三、

一些常见问题
Q&A

及时更新
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: