Article Image
Article Image
Want to keep up to date with the latest posts and videos? Subscribe to the newsletter
HELP SUPPORT MY WORK: If you're feeling flush then please stop by Patreon Or you can make a one off donation via ko-fi
#BOX2D #IPHONE #PHYSICS ENGINE #PINBALL GAME #TUTORIAL

I recently gave a presentation at the LiDG on this - the slides can be found here.

The complete set of demo projects for this blog post can be found here (thanks to Terry for pointing out the missing files in the original set of zips).

Box2D is an open source 2D physics engine that has proved popular with iPhone developers.

One thing to bear in mind with Box2D is it is just a physics engine - all the drawing and rendering of the objects is down to you.

The engine is tuned for meters-kilograms-seconds - so you can just feed in objects in pixels units, you should apply some kind of scaling to your objects so that they are in the 0.1 - 10 meter range.

There are several concepts that it’s useful to be familiar with:

• Rigid Body/Body - chunk of matter that is so strong it cannot be compressed
• Shape - 2D pices of collision geometry that is attached to a body
• Friction, Restitution (bouncyness)
• Constraint - Physical connection that removes degrees of freedom from a body
• World - Collection of bodies, shapes, and constraints interacting together

You can download Box2D from sourceforge or Google code. I chose to use a revision from the sourceforge repository that compiles for the iPhone and also matches the online documentation:

svn co https://box2d.svn.sourceforge.net/svnroot/box2d box2d -r 210

Once you’ve dwonloaded the code add the source and include folder to your xCode project as shown in the diagram:

<img style=”display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 115px;” src=”http://2.bp.blogspot.com/_jO69rW-vio4/S2XVi5wjxzI/AAAAAAAAB98/oaxsE4MnLoM/s320/Screen+shot+2010-01-31+at+14.09.13.png” border=”0” alt=”“id=”BLOGGER_PHOTO_ID_5432983321089132338” />

To get Box2D building for the iPhone you need to add to your projects -DTARGET_OS_IPHONE additional CFLAGS

<img style=”display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 154px;” src=”http://4.bp.blogspot.com/_jO69rW-vio4/S2XfpxiBDII/AAAAAAAAB-M/SOvZsL7KqsE/s400/Screen+shot+2010-01-31+at+14.52.48.png” border=”0” alt=”“id=”BLOGGER_PHOTO_ID_5432994434256014466” />

You’ll also need to change your file extension from .m to .mm as Box2D uses C++.

Now we can start to use the Box2D engine to do something useful. For this walkthrough we’re going to create a simple pin-ball game. <img style=”display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 275px; height: 400px;” src=”http://4.bp.blogspot.com/_jO69rW-vio4/S2XgUxJ92HI/AAAAAAAAB-U/NuAFDy_IrLI/s400/Screen+shot+2010-01-31+at+14.55.35.png” border=”0” alt=”“id=”BLOGGER_PHOTO_ID_5432995172889516146” /> The image above shows our main game view - each of the objects are UIImageViews. We’ll use these to show the locations of the objects in our physics simulation.

The first thing we need to do is create our physics world. This object is responsible or managing the memory for our physics objects and simulating their interactions. Our physics world also has gravity.

.h
// the world
b2World *myWorld;

.m
// create the world
b2AABB worldAABB;
worldAABB.lowerBound.Set(-100.0f, -100.0f);
worldAABB.upperBound.Set(100.0f, 100.0f);
b2Vec2 gravity(0.0f, -2.0f);
myWorld=new World(worldAABB, gravity, true);


When we want to simulate the world we move it forward by a time step. Ideally this time stap should be fast and regular. In the sample code below we’ll be running our world 30 times a second.

-(void) runWorld {
// step the world forward
myWorld->Step(1.0f/30.0f, 10, 10);
}

-(void) viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
animationTimer=[NSTimer scheduledTimerWithTimeInterval:1.0f/30.0f target:self selector:@selector(runWorld) userInfo:nil repeats:YES];
}

-(void) viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[animationTimer invalidate];
animationTimer=nil;
}


Now we’ve got our world we can add some objects to it. A body has position, rotation and velocity. You can apply forces, torques and impulses to them to.

A body can be static or dynamic. Static bodies do not move and do not interact with other static bodies (we’ll be using static bodies for the planets and edges of the pinball table.

Bodies are the backbone for shapes. Two shapes on the same body never move relative to each other.

A body is built from:

• A body definition
• Position and angle
• Damping (linear and angular)
• One or more shape definitions
• Friction
• Restitution
• Density

The code shown below creates a body for the ball bearing in our game:

b2BodyDef ballBodyDef;
ballBodyDef.position.Set(S2W(self.ballView.center.x),
S2W(self.ballView.center.y));
ballBodyDef.linearDamping=0.5;
ballBodyDef.angularDamping=0.5;
ballBody=myWorld->CreateBody(&ballBodyDef);
b2CircleDef ballShapeDef;
S2W(self.ballView.bounds.size.width/2);
ballShapeDef.density= 0.1f;
ballShapeDef.friction= 0.3f;
ballShapeDef.restitution = 0.2f;
ballBody->CreateShape(&ballShapeDef);
ballBody->SetMassFromShapes();


To find out where our body is at any time we can query the body for its position, velocity, rotation and other attributes.

The code below updates our ball view to the position of the ball in the physics world:

// find out where our ball should be
b2Vec2 position = ballBody->GetPosition();
ballView.center=CGPointMake(W2S(position.x),
W2S(position.y));


If you run up Demo 1 you can see this code in action. You can reset the balls location by touching the screen.

Obviousy we need some walls around the world to stop the ball escaping and the ball should be bouncing off the planets. We’ll create static shapes for these objects. To create a static shape, just give it no mass - adding walls and the planets gives us Demo 2.

The next step is to wire up the flippers. For this we need to create some joints. Box2D offers us a number of options for joining objects together:

<img style=”display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 335px;” src=”http://4.bp.blogspot.com/_jO69rW-vio4/S2XXgVjbJcI/AAAAAAAAB-E/sN1oViv_lwY/s400/Screen+shot+2010-01-31+at+14.17.47.png” border=”0” alt=”“id=”BLOGGER_PHOTO_ID_5432985476033881538” /> For our purposed we’ll be using a revolute joint to connect our flipper to the shoulders of the pinball table.

 b2RevoluteJointDef jointDefLeftPaddle;


To make our flippers move we’ll apply torque (rotational force) to the body when the user touches the screen. We’ll also play a sound at the same time.

if(touchPos.y>400 && touchPos.x<90) {
AudioServicesPlaySystemSound(flipperSound);
} else if(touchPos.y>400 && touchPos.x>210) {
AudioServicesPlaySystemSound(flipperSound);
}


Demo 3 shows this all working. We’ve now got an almost complete game. All that’s left it to detect when the ball collides with the planets and other things.

Box2D create contacts to manage collisions between shapes. These have:

• Contact point - where the shapes touch
• Contact normal - points from shape1 to shape2
• Contact seperation - opposite of penetration
• Normal Force - collision intensity
• Tangent Force - friction force

To listen for contacts we need to create a C++ class that implements the b2ContactListener interface. This has the following methods:

• Persist - a contact persisted for more than one timestep
• Remove - contact removed
• Result - computed results for contact

One thing to be aware of is that within a single timestep you might receive multiple notifications of contacts between objects. In my code I simply set a flag to indicate what the ball has collided with and process it after the world step has completed.

class ContactListener : public b2ContactListener {
PinBallViewController *pinBallViewController;
public:
ContactListener(PinBallViewController *controller) : pinBallViewController(controller) {}
void Result(const b2ContactResult* point) {
b2Body *body1=point->shape1->GetBody();
b2Body *body2=point->shape2->GetBody();

[pinBallViewController contactBetween:body1 andBody:body2 withForce:point->normalImpulse];
}
};

contactListener=new ContactListener(self);
myWorld->SetContactListener(contactListener);


With this in place we can detect when the ball hits the planets, the walls and the flippers. The complete demo (Demo4) shows this all working. We’ve got a basic working game in a couple of 100 lines of code!

Feel free to reuse any of the code in your own projects.

#BOX2D #IPHONE #PHYSICS ENGINE #PINBALL GAME #TUTORIAL

## Related Posts

NeHe OpenGL tutorial 2, 3 and 4 ported to ES 2.0 - Master the art of porting NeHe OpenGL tutorials to OpenGLES 2.0 on the iPhone, beginning with simple tasks like drawing a triangle and square while exploring vertex and fragment shader code.
GameKit and GameCenter - Learn the art of creating real-time multiplayer games with GameKit and GameCenter by exploring these comprehensive notes and slides from an engaging iOSDevUK talk.
Tablet+iPhones = Console+Controllers - Connect iPhones as wireless controllers and a tablet as a console utilizing gamekit for unique gaming experiences, from Wii-style games to virtual card tables.
Shoot3D for the iPad/iPhone - Explore the exciting 3D game I've launched on the app store and learn about the development process and key insights gained from creating this unique gaming experience.
Creating an OpenGL game for both the Palm and iOS - Dive into the experience of porting an OpenGL game from iOS to Palm PDK, highlighting the differences in development, debugging, and review processes between the two platforms.

## Related Videos

Pong on the apple watch - Experience the excitement of playing Pong on an Apple Watch! Check out this enthralling demo created at the iOSDevUK event by the talented atomic14 team.
Tanks! for the Palm Pre and Palm Pixie - Check out the fascinating process of porting an iPhone app to a Palm Pre Plus, showcasing the versatility of app development.
3D Printed Game Controller Designed in Fusion 360 - Master the art of designing and building your own game controller with 3D printing, Fusion 360, and ESP32 components in this comprehensive tutorial.
Laser Projected Asteroids - Reinventing the classic arcade game with Frickin Laser Beams! - Explore the creation of a classic Arduino ESP32 Asteroids game using laser projection, providing an in-depth look at system hardware, firmware, and game engine. See font demonstrations and learn about audio output, while accessing schematics to try the game out for yourself.
Browser-Based Augmented Reality Sudoku Solver using TensorFlow and Image Processing - Learn how to build a Sudoku app using browser APIs and modern techniques, including image processing pipeline, TensorFlow-powered neural networks, and OCR to efficiently identify, extract, and solve Sudoku puzzles.
HELP SUPPORT MY WORK: If you're feeling flush then please stop by Patreon Or you can make a one off donation via ko-fi
Want to keep up to date with the latest posts and videos? Subscribe to the newsletter
> Image