View All Posts
read
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 #CODING #GAME DEVELOPMENT #IPHONE #OPEN SOURCE #PHYSICS ENGINE #PHYSICS SIMULATION

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;
ballShapeDef.radius=
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;
 jointDefLeftPaddle.Initialize(leftSlopeBody, leftPaddleBody,  
          b2Vec2(S2W(self.leftPaddleView.frame.origin.x), S2W(self.leftPaddleView.frame.origin.y)));
 jointDefLeftPaddle.lowerAngle = -0.25*b2_pi;
 jointDefLeftPaddle.upperAngle = 0.25*b2_pi;
 jointDefLeftPaddle.enableLimit = true;
 myWorld->CreateJoint(&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) {
 leftPaddleBody->ApplyTorque(-500);
 AudioServicesPlaySystemSound(flipperSound);
} else if(touchPos.y>400 && touchPos.x>210) {
 rightPaddleBody->ApplyTorque(500);
 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:

  • Add - a contact has been added
  • 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 #CODING #GAME DEVELOPMENT #IPHONE #OPEN SOURCE #PHYSICS ENGINE #PHYSICS SIMULATION

Related Posts

Creating an OpenGL game for both the Palm and iOS - I've made a triumphant return to the blogosphere with the release of my new game, 'Tanks!' developed for Palm Pre/Pixie and soon for iPhone devices. The game, an experiment to learn OpenGLES 2.0, is a testament to the feasibility of porting C++ or C code from iOS to Palm PDK, despite minor challenges with UI interaction and audio. So gear up, folks! Download 'Tanks!', step onto the battlefield and let the mayhem begin! Next stop on my coding odyssey - Android!
GameKit and GameCenter - Had a blast at iOSDevUK - a fantastic conference that was not only filled with intriguing talks, but also offered me the opportunity to present my own talk. I discussed making real time multiplayer games using GameKit and GameCenter. The slides and notes from my talk are available for download if you're interested!
NeHe OpenGL tutorial 5 ported to ES2.0 - In this blog post, I delve into the specifics of porting code for drawing 3D shapes in ES2.0. I detail how to overcome the lack of depth buffer in the default OpenGL template and describe how to add rotation to objects by saving the model view matrix. This post offers a useful walkthrough, especially for those keen to deepen their understanding of 3D rendering nuances in ES2.0.
NeHe OpenGL tutorial 2, 3 and 4 ported to ES 2.0 - As I strove to learn OpenGLES 2.0 for new gaming projects on iPhone and Palm Pre, I faced certain challenges due to the introduction of a programmable graphics pipeline in OpenGLES 2.0. With this mechanism, we are responsible for writing the code to generate our graphics, which was overwhelming at first. To help others, I ported some of the NeHe tutorials over to OpenGLES2.0 on iPhone in an easily-digestible way. In this post, you will find a walkthrough of the first 4 tutorials, complete with codes, explanations and screenshots to make learning easier.
Raspberry Pi BTLE Device - Just wrapped up the first iOSCon hackathon and had a blast tinkering with my Raspberry Pi, turning it into a full-fledged Bluetooth device in sync with an iPhone app. Used node for setting up and Bleno for creating Bluetooth low energy peripherals. Penned down each step for you to replicate, right from writing strings on my LCD to reading temperatures and getting notified of IR remote button clicks. Ran it on an app store or GitHub test application. Also, explored the Core Bluetooth framework for iOS app creation, for reading and writing data to the Raspberry Pi. Let's keep creating magic with technology!

Related Videos

Pong on the apple watch - Get a glimpse of a quick demo on playing Pong on the Apple Watch, skillfully hacked together at the iOSDevUK event! Don't miss out!
AR Sudoku Solver in Your Browser: TensorFlow & Image Processing Magic - Discover how to recreate a Sudoku app using browser APIs and ecosystem advancements, and explore the image processing pipeline technique for extracting Sudoku puzzles and solving them.
Sneak Preview of work in progress. - Dive into the fascinating world of PCB coils with this informative video, showcasing innovative ways to create and experiment with them. Get ready to be inspired by @CarlBugeja's groundbreaking work!
Tanks! for the Palm Pre and Palm Pixie - Witness the successful porting of an iPhone app to a Palm Pre Plus in this intriguing video!
Laser Projected Asteroids: ESP32 Reinvents Classic Arcade Game! - Learn how to create a classic Arduino ESP32 Asteroids game with laser projection, including a tour of the system hardware and a look at its firmware and game engine. Watch a demonstration and comparison of fonts, as well as an overview of the audio output. Dive into the schematics and try out the game for yourself!
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
Blog Logo

Chris Greening


Published

> Image

atomic14

A collection of slightly mad projects, instructive/educational videos, and generally interesting stuff. Building projects around the Arduino and ESP32 platforms - we'll be exploring AI, Computer Vision, Audio, 3D Printing - it may get a bit eclectic...

View All Posts