Qt + Box2D is easy!

Box2D is an Open Source rigid body 2D physics engine for C++. It's currently (2.0.1) released under the MIT license, which is quite permissive. Box2D is used by, among other things, Gluon (http://gluon.tuxfamily.org/), which is a game library from KDE in-the-making.

Integrating Box2D into your Qt application is quite easy, and this blog shows you how to get started. First of all:

* Step 1: Download Box2D from Google Code: http://code.google.com/p/box2d/
* Step 2: Build it (I had to insert a few #include <cstring> to get it to build)
* Step 3: Build and try the test bed application: Box2D/Examples/TestBed/
* Step 4: Read the manual: http://www.box2d.org/manual.html
* Step 5: Continue reading this blog to hook up the two frameworks...

The library doesn't seem to install, so I just compiled it in-source and used it directly.

What I found during my approx 2 hour study today was that Box2D manages a world with bodies, similar to how QGraphicsScene manages items. In short, you create a world object and populate it with elements. Some bodies are static, like the ground, and some dynamic, like a bouncing ball. You can define joints, masses, friction, and other parameters, define a gravity vector, and then start simulating. Box2D doesn't require a graphics system - any scene graph with elements that you can move and rotate should do fine. Graphics View works quite well. :-) I've based this code on the provided "Hello World" example that comes with Box2D.

The world object defines the bounds of the coordinate system and the gravity vector. It feels very similar to QGraphicsScene. The bounds are, according to the docs, not enforced, but I got many run-time aborts when items are outside these bounds so you better make the world large enough to cover all your items.

// Define world, gravity
b2AABB worldAABB;
worldAABB.lowerBound.Set(-200, -100);
worldAABB.upperBound.Set(200, 500);
b2World world = new b2World(worldAABB,
/* gravity = */ b2Vec2(0.0f, -10.0f),
/* doSleep = */ true);

Bodies in Box2D have a position and an angle, and you can assign a shape to it (convex polygon or circular). This feel similar to how QGraphicsItem has a position and a transform. In fact with 4.6 the rotation property fits perfectly with the angle in Box2D (except Box2D uses radians and rotates the opposite direction from QGraphicsItem). This example shows how to create a body, and then assign a rectangular shape:

b2BodyDef bodyDef;
bodyDef.position.Set(0.0f, -10);
b2Body *body = world->CreateBody(&bodyDef);

b2PolygonDef shapeDef;
shapeDef.SetAsBox(100.0f, 10.0f);
body->CreateShape(&shapeDef);

Bodies can either be static or dynamic. Static bodies simply don't move. By default, bodies are static. To make a body dynamic, you assign a positive mass. The easiest way to do that is to ask Box2D to calculate mass and rotational inertia by looking at the shape of the body. So modifying the above slightly:

shapeDef.density = 1.0f;
shapeDef.friction = 0.5f;
body->CreateShape(&shapeDef);
body->SetMassFromShapes();

That's really all there is to it. When you're ready, advance the simulation step by step by calling b2World::Step like this:

world->Step(B2_TIMESTEP, B2_ITERATIONS);

After calling this function, Box2D will have adjusted positions and angles of all bodies. So if you have corresponding items in Graphics View, you can just update their positions and rotations like this:

void adjust()
{
// Update QGraphicsItem's position and rotation from body.
b2Vec2 position = _body->GetPosition();
float32 angle = _body->GetAngle();
setPos(position.x, -position.y);
setRotation(-(angle * 360.0) / (2 * PI));
}

Notice the negative Y (as Graphics View, like the rest of Qt, has a Y component that points downwards), and the negative rotation which is converted to degrees.

That's really all there is. Create the world, add body elements, assign mass, and start the simulation. Use the angle and position to adjust your QGraphiscItems, and enjoy :-).

The above video shows my first Box2D + Graphics View application in action. You can find the full sources here: qgv-box2dtar.gz. I've tried to experiment a bit with how Box2D bindings for Qt could be done. For now I'll leave it as an experiment.


Blog Topics:

Comments

?
Stefan Majewsky
0 points
184 months ago

My tips for everyone who wants to use Box2D in Qt apps:

  1. You should have a look at my CMake patch for Box2D which is at http://code.google.com/p/bo... - this makes it possible to make install everything and simply use find_package(Box2D) in one's own application.
  2. For a more sophisticated usage example of Box2D, have a look at svn://anonsvn.kde.org/home/...
?
boulabiar
0 points
184 months ago

How to increase the speed of the simulation ?
it runs very bad in my Computer !

Have you tried other physics engines to work inside QGraphicsView ?
Chipmunk or others ?
http://www.youtube.com/watc...

The speed is very bad to be used in any app.

?
Kevin Kofler
0 points
184 months ago

I wonder if multiple inheritance or some approximation to it could be used to make objects which are both QGraphicsView items and Box2D objects at the same time and automatically keep coordinates etc. in sync. Of course that would be very much un-MVC-like, but I suspect it'd make things simpler by eliminating redundancy and prevent inconsistencies beween graphics and physics.

?
Mark Harrison
0 points
184 months ago

Nifty!

Would you consider doing a similar project with Chipmunk? It's derived from Box2D, and is currently very popular as it's been ported to the iphone.

?
Andreas
0 points
184 months ago

The performance depends on the complexity of the graphics and which graphics system you are running. This is typical for any graphics app written in Qt. In this example each element is a triangle with an outline, with antialiasing enabled, and it runs at decent speed on anything but X11. If you run the app with "-graphicssystem opengl" or "-graphicssystem raster", it performs well. Still, you can simplify the graphics by using simple sprites instead.

?
Thorbj&#248;rn Lindeijer
0 points
183 months ago

@designker (and others interested in combining this with QML): I've made a start on integrating Box2D in QML by using an extension plugin. The code can be found at http://gitorious.org/qmlarcade (it also has an extension plugin supporting tile maps made with Tiled, a tool I develop in my spare time). It should compile and run fine with the latest qt-4.7.

?
hp
0 points
183 months ago

I ppl

I use the CodeBlocks and open "Box2Dv2.0.1Box2Dv2.0.1Box2DBuildCodeBlocksBox2D.workspace"
next I Build and create 3 files:
libBox2D.a
libFreeGLUT.a
libGLUI.a

I put the 3 files in C:Qt2010.02.1mingwlib but when i try use the example, in the
b2World world = new b2World(worldAABB, b2Vec2(0.0f, -10.0f), true);
give-me a error:

:/qt/2010.02.1/mingw/bin/../lib/gcc/mingw32/4.4.0/../../../libbox2d.a(b2World.o): In function `ZNK7b2Joint7GetTypeEv':

any help ?

tks

?
hp
0 points
182 months ago

Can you put all the steps ?

?
Adam Higerd
-1 points
184 months ago

I've been using Box2D with QGraphicsView for a long time. It really does work great. I hacked up a little pinball/Peggle-esque game with it last year.

?
designker
-1 points
184 months ago

Could this be used with QML to provide an easy way to make games?

?
bunjee
-1 points
184 months ago

Hey Andreas,

I'm currently working integrating a few libraries with Qt to make it a "game factory power house".

So far I've added the Ogre engine.
It's a smart move because it grants you particles, lights etc... out of the box.

I think Box2D might be the next step (A Network game engine would be sweet too).

I pay attention to licenses, I'm trying to use LGPL or less, Box2D fall into that categorie.

Now I have two questions :
- Could we use this in QtScript using Qt ScriptGenerator (I happen to use this one quite a lot, it speeds up development greatly) ?
- A little off topic but, is there a way to integrate Ogre smartly with QGraphicsScene to make these two fits naturally ?

All in all, It seems obvious that tuned up nicely, Qt might become a strong alternative to flash for making games.

Benjamin Arnaud.

?
Roberto Alsina
-1 points
184 months ago

A while ago I did a similar thing with chipmunk and pyqt:

http://www.youtube.com/watc...

Code here: http://chipscene.googlecode...

?
spaceman
-1 points
184 months ago

Are there any plans to integrate (something like) Box2D into the Qt-Framework itself?
QGraphicsView would be a natural candidate to have native physics support as all the basic infrastructure is already present.
It would be really amazing to just add some properties to a QGraphics(Physic)Item like setMass(qfloat m) and have a step() function on a QGraphics(Physic)Scene.

?
boulabiar
-1 points
184 months ago

Hi,

The example works with very bad performance.
From where comes that problem ? Qt or from Box2d ?

Anyway, Andreas, can you edit the post and move the source link to up, just before the video because I have only see it after at least 1h from reading (didn't expect links after a video !)

For those who want a modified Box2d lib without messing to add the "#include ", and with Andreas's example, you can download it from here :
http://boulabiar.net/box2d/...

?
SABROG
-1 points
184 months ago

boulabiar, can't compile with MinGW/MSYS ...

MSYS:
$ make
(cd Contrib/freeglut; make)
make[1]: Entering directory `/c/SABROG/Box2Dm/Contrib/freeglut'
gcc -g -O2 -DTARGETHOSTUNIXX11 -DHAVEFCNTLH -DHAVESYSIOCTLH -c -o freeglutcallbacks.o freeglutcallbacks.c
freeglutcallbacks.c:28:25: error: GL/freeglut.h: No such file or directory
In file included from freeglut
callbacks.c:29:
freeglutinternal.h:46:1: warning: "TARGETHOSTUNIXX11" redefined
: warning: this is the location of the previous definition

MinGW:
(cd Contrib/freeglut; make)
process_begin: CreateProcess(NULL, (cd Contrib/freeglut; make), ...) failed.
make (e=2): ═х єфрхЄё  эрщЄш єърчрээ√щ Їрщы.
mingw32-make: *** [all] Error 2

Few years ago i see Box2D example in dojo project, but he's missing.

?
SABROG
-1 points
184 months ago

Andreas, archive name is broken: qgv-box2dtar.gz instead qgv-box2d.tar.gz

?
boulabiar
-1 points
184 months ago

I have only tested it on Linux,
TARGETHOSTUNIX_X11

?
SABROG
-1 points
184 months ago

Andreas, you forgot #include in main.cpp

How i compile box2d with MinGW. Open MSYS and go to Source subdirectory, call make. After compiling open windows console (not MSYS) and go to qgv-box2d project path. Then edit .pro file for qgv-box2d and set your path to box2d header and library. Open main.cpp and add #include .
Run qmake && mingw32-make release && releaseqgv-box2d.exe

This my result: http://img408.imageshack.us... (animated gif ~500Kb)

?
SABROG
-1 points
184 months ago

I forget what this blog don't support angle brackets. So you need include in main.cpp

?
SABROG
-1 points
184 months ago

:( time.h