# Cocos2d: Uses of Box2D Physics Engine

Your details (so we can tell your friend who this is from) *
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
v
B
7
p
j
k
by Nathan Burba | December 2011 | Open Source

For years, physics engines have been used in video games to add a sense of realism to the action onscreen. In many games, physics plays a crucial role within the gameplay. Cocos2d comes bundled with two popular 2D physics engines: Box2D and Chipmunk. In this article, we will explain the most common uses of physics in games using Box2D as our engine of choice.

In this article by Nathan Burba, author of Cocos2d for iPhone 1 Game Development Cookbook, we will cover the following points:

• Box2D setup and debug drawing
• Creating collision response routines
• Using different shapes
• Dragging and collision filtering

(For more resources on Cocos2d, see here.)

# Box2D setup and debug drawing

In our first physics recipe, we will explore the basics of creating a Box2D project and setting up a Box2D world. The example creates a scene that allows the user to create realistic 2D blocks.

Please refer to the project RecipeCollection02 for full working code of this recipe.

## How to do it...

The first thing we need to do is create a Box2D project using the built-in Box2D project template:

1. Go to File | New Project.
2. Under User Templates click on Cocos2d.
3. Now, right click on Cocos2d Box2d Application.

4. Click Choose, name your project, and hit Save.

Now, execute the following code:

`#import "Box2D.h"#import "GLES-Render.h"//32 pixels = 1 meter#define PTM_RATIO 32@implementation Ch4_BasicSetup-(CCLayer*) runRecipe {  [super runRecipe];  /* Box2D Initialization *///Set gravity  b2Vec2 gravity;  gravity.Set(0.0f, -10.0f);  //Initialize world  bool doSleep = YES;  world = new b2World(gravity, doSleep);  world->SetContinuousPhysics(YES);  //Initialize debug drawing  m_debugDraw = new GLESDebugDraw( PTM_RATIO );  world->SetDebugDraw(m_debugDraw);  uint32 flags = 0;  flags += b2DebugDraw::e_shapeBit;  m_debugDraw->SetFlags(flags);  //Create level boundaries  [self addLevelBoundaries];  //Add batch node for block creation  CCSpriteBatchNode *batch = [CCSpriteBatchNodebatchNodeWithFile:@"blocks.png" capacity:150];  [self addChild:batch z:0 tag:0];  //Add a new block  CGSize screenSize = [CCDirector sharedDirector].winSize;  [self addNewSpriteWithCoords:ccp(screenSize.width/2, screenSize.height/2)];  //Schedule step method  [self schedule:@selector(step:)];  return self;}/* Adds a polygonal box around the screen */-(void) addLevelBoundaries {  CGSize screenSize = [CCDirector sharedDirector].winSize;  //Create the body  b2BodyDef groundBodyDef;  groundBodyDef.position.Set(0, 0);  b2Body *body = world->CreateBody(&groundBodyDef);  //Create a polygon shape  b2PolygonShape groundBox;  //Add four fixtures each with a single edge  groundBox.SetAsEdge(b2Vec2(0,0), b2Vec2(screenSize.width/PTM_RATIO,0));  body->CreateFixture(&groundBox,0);  groundBox.SetAsEdge(b2Vec2(0,screenSize.height/PTM_RATIO),b2Vec2(screenSize.width/PTM_RATIO,screenSize.height/PTM_RATIO));  body->CreateFixture(&groundBox,0);  groundBox.SetAsEdge(b2Vec2(0,screenSize.height/PTM_RATIO),b2Vec2(0,0));  body->CreateFixture(&groundBox,0);  groundBox.SetAsEdge(b2Vec2(screenSize.width/PTM_RATIO,screenSize.height/PTM_RATIO), b2Vec2(screenSize.width/PTM_RATIO,0));  body->CreateFixture(&groundBox,0);}/* Adds a textured block */-(void) addNewSpriteWithCoords:(CGPoint)p {  CCSpriteBatchNode *batch = (CCSpriteBatchNode*) [selfgetChildByTag:0];  //Add randomly textured block  int idx = (CCRANDOM_0_1() > .5 ? 0:1);  int idy = (CCRANDOM_0_1() > .5 ? 0:1);  CCSprite *sprite = [CCSprite spriteWithBatchNode:batchrect:CGRectMake(32 * idx,32 * idy,32,32)];  [batch addChild:sprite];  sprite.position = ccp( p.x, p.y);  //Define body definition and create body  b2BodyDef bodyDef;  bodyDef.type = b2_dynamicBody;  bodyDef.position.Set(p.x/PTM_RATIO, p.y/PTM_RATIO);  bodyDef.userData = sprite;  b2Body *body = world->CreateBody(&bodyDef);  //Define another box shape for our dynamic body.  b2PolygonShape dynamicBox;  dynamicBox.SetAsBox(.5f, .5f);//These are mid points for our 1m box  //Define the dynamic body fixture.  b2FixtureDef fixtureDef;  fixtureDef.shape = &dynamicBox;  fixtureDef.density = 1.0f;  fixtureDef.friction = 0.3f;  body->CreateFixture(&fixtureDef);}/* Draw debug data */-(void) draw {  //Disable textures  glDisable(GL_TEXTURE_2D);  glDisableClientState(GL_COLOR_ARRAY);  glDisableClientState(GL_TEXTURE_COORD_ARRAY);  //Draw debug data  world->DrawDebugData();  //Re-enable textures  glEnable(GL_TEXTURE_2D);  glEnableClientState(GL_COLOR_ARRAY);  glEnableClientState(GL_TEXTURE_COORD_ARRAY);}/* Update graphical positions using physical positions */-(void) step: (ccTime) dt {  //Set velocity and position iterations  int32 velocityIterations = 8;  int32 positionIterations = 3;  //Steo the Box2D world  world->Step(dt, velocityIterations, positionIterations);  //Update sprite position and rotation to fit physical bodies  for (b2Body* b = world->GetBodyList(); b; b = b->GetNext()) {   if (b->GetUserData() != NULL) {    CCSprite *obj = (CCSprite*)b->GetUserData();    obj.position = CGPointMake( b->GetPosition().x * PTM_RATIO,b->GetPosition().y * PTM_RATIO);    obj.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle());   }  }}/* Tap to add a block */- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {  for( UITouch *touch in touches ) {   CGPoint location = [touch locationInView: [touch view]];   location = [[CCDirector sharedDirector] convertToGL: location];   [self addNewSpriteWithCoords: location]; }}@end`

## How it works...

The Box2D sample project is a simple way to understand what a physics system looks like.

• Initialization:
Upon initialization of the b2World object, we set a few things including gravity, object sleeping, and continuous physics. Sleeping allows bodies that are at rest to take up less system resources. Gravity is typically set to a negative number in the Y direction but can be reset at any time using the following method on b2World:
`void SetGravity(const b2Vec2& gravity);`

In addition to storing a pointer to the main b2World instance, we also usually store a pointer to an instance of GLESDebugDraw.

• Debug drawing:
Debug drawing is handled by the GLESDebugDraw class as defined in GLESRender.h. Debug drawing encompasses drawing five different elements onscreen. These include shapes, joint connections, AABBs (axis-aligned bounding boxes), broad-phase pairs, and a center of mass bit.
• Visual to physical drawing ratio:
We define the constant PTM_RATIO at 32, to allow consistent conversion between the physical world and the visual world. PTM stands for pixel to meter. Box2D measures bodies in meters and is built and optimized to work with bodies between the sizes of 0.1 to 10.0 meters. Setting this ratio to 32 is a common convention for optimal shapes to appear between 3.2 to 320 pixels on screen. Optimization aside, there is no upper or lower limit to Box2D body size.
• Level boundaries:
In this and many future examples, we add a level boundary roughly encompassing the entire screen. This is handled with the creation of a b2Body object with four fixtures. Each fixture has a b2Polygon shape that defines a single edge. Creating an edge typically involves the following:
`b2BodyDef bodyDef;bodyDef.position.Set(0, 0);b2Body *body = world->CreateBody(&bodyDef);b2PolygonShape poly;poly.SetAsEdge(b2Vec2(0,0), b2Vec2(480/PTM_RATIO,0));body->CreateFixture(&poly,0);`

Because these edges have no corresponding visual components (they are invisible), we do not need to set the bodyDef.userData pointer.

• Creating the blocks:
Blocks are created much in the same way that the level boundaries are created. Instead of calling SetAsEdge, we call SetAsBox to create a box-shaped polygon. We then set the density and friction attributes of the fixture. We also set bodyDef.userData to point to the CCSprite we created. This links the visual and the physical, and allows our step: method to reposition sprites as necessary.
• Scheduling the world step:
Finally, we schedule our step method. In this method, we run one discrete b2World step using the following code:
`int32 velocityIterations = 8;int32 positionIterations = 3;world->Step(dt, velocityIterations, positionIterations);`

The Box2D world Step method moves the physics engine forward one step. The Box2D constraint solver runs in two phases: the velocity phase and position phase. These determine how fast the bodies move and where they are in the game world. Setting these variables higher results in a more accurate simulation at the cost of speed. Setting velocityIterations to 8 and positionIterations to 3 is the suggested baseline in the Box2D manual. Using the dt variable syncs the logical timing of the application with the physical timing. If a game step takes an inordinate amount of time, the physics system will move forward quickly to compensate. This is referred to as a variable time step. An alternative to this would be a fixed time step set to 1/60th of a second. In addition to the physical step, we also reposition and re-orientate all CCSprites according to their respective b2Body positions and rotations:

`for (b2Body* b = world->GetBodyList(); b; b = b->GetNext()) { if (b->GetUserData() != NULL) {  CCSprite *obj = (CCSprite*)b->GetUserData();  obj.position = CGPointMake( b->GetPosition().x * PTM_RATIO,b->GetPosition().y * PTM_RATIO);  obj.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle()); }}`

Taken together, these pieces of code sync the physical world with the visual.

## Cocos2d for iPhone 1 Game Development Cookbook

 Over 90 recipes for iOS 2D game development using cocos2d with this book and ebook
Published: December 2011
eBook Price: \$29.99
Book Price: \$49.99
See more

(For more resources on Cocos2d, see here.)

# Creating collision response routines

To make efficient and organized use of Box2D, we must create a few wrapper classes to encapsulate specific functionality. In this recipe, we will use these classes to add collision response routines to our simple falling block demo from the previous recipe.

Please refer to the project RecipeCollection02 for full working code of this recipe. Also, note that some code has been omitted for brevity.

## How to do it...

Execute the following code:

`/* GameObject.h */@interface GameObject : CCNode { @public  GameArea2D *gameArea; b2Body *body; b2BodyDef *bodyDef;  b2FixtureDef *fixtureDef; b2PolygonShape *polygonShape;  b2CircleShape *circleShape; CCSprite *sprite;  int typeTag; bool markedForDestruction;}/* GameSensor.h */@interface GameSensor : GameObject {}@property (readonly) int type;@end/* GameMisc.h */@interface GameMisc : GameObject { @public  float life;}@property (readonly) int type;@property (readwrite, assign) float life;@end/* BasicContactListener.h */class basicContactListener : public b2ContactListener{ public:  void BeginContact(b2Contact* contact);};void basicContactListener::BeginContact(b2Contact* contact){ b2Body *bodyA = contact->GetFixtureA()->GetBody(); b2Body *bodyB = contact->GetFixtureB()->GetBody(); //Handle collision using your custom routine if(bodyA and bodyB){  GameObject *objA = (GameObject*)bodyA->GetUserData();  GameObject *objB = (GameObject*)bodyB->GetUserData();  GameArea2D *gameArea = (GameArea2D*)objA.gameArea;  [gameArea handleCollisionWithObjA:objA withObjB:objB]; }}/* GameArea2D.h */@implementation GameArea2D-(CCLayer*) runRecipe { /* CODE OMITTED */ //Add contact filter and contact listener world->SetContactListener(new basicContactListener); /* CODE OMITTED */ //Add button to hide/show debug drawing CCMenuItemFont* swapDebugDrawMIF = [CCMenuItemFontitemFromString:@"Debug Draw" target:self selector:@selector(swapDebugDraw)]; CCMenu *swapDebugDrawMenu = [CCMenu menuWithItems:swapDebugDrawMIF,nil];  swapDebugDrawMenu.position = ccp( 260 , 20 );  [self addChild:swapDebugDrawMenu z:5]; //Schedule our every tick method call [self schedule:@selector(step:)]; return self;}/* This is called from 'basicContactListener'. It will need to beoverridden. */-(void) handleCollisionWithObjA:(GameObject*)objAwithObjB:(GameObject*)objB { /** ABSTRACT **/}/* Destroy the world upon exit */- (void) dealloc { delete world; world = NULL; delete m_debugDraw; [super dealloc];}/* Debug information is drawn over everything */-(void) initDebugDraw { DebugDrawNode * ddn = [DebugDrawNode createWithWorld:world]; [ddn setPosition:ccp(0,0)]; [gameNode addChild:ddn z:100000];}/* When we show debug draw we add a number of flags to show specificinformation */-(void) showDebugDraw { debugDraw = YES; uint32 flags = 0; flags += b2DebugDraw::e_shapeBit; flags += b2DebugDraw::e_jointBit; flags += b2DebugDraw::e_aabbBit; flags += b2DebugDraw::e_pairBit; flags += b2DebugDraw::e_centerOfMassBit; m_debugDraw->SetFlags(flags);}@end@implementation Ch4_CollisionResponse-(CCLayer*) runRecipe {  /* CODE OMITTED */ //Create circular GameSensor object GameSensor *gameObjSensor = [[GameSensor alloc] init]; gameObjSensor.gameArea = self; //Create the body definition gameObjSensor.bodyDef->type = b2_staticBody; gameObjSensor.bodyDef->position.Set(240/PTM_RATIO,160/PTM_RATIO); gameObjSensor.bodyDef->userData = gameObjSensor; //Create the body gameObjSensor.body = world->CreateBody(gameObjSensor.bodyDef); //Create the shape and fixture gameObjSensor.circleShape = new b2CircleShape(); gameObjSensor.circleShape->m_radius = 1.0f; //Create the fixture definition gameObjSensor.fixtureDef->shape = gameObjSensor.circleShape; gameObjSensor.fixtureDef->isSensor = YES; //Create the fixture gameObjSensor.body->CreateFixture(gameObjSensor.fixtureDef); //Create level boundaries [self addLevelBoundaries]; //Add block batch sprite CCSpriteBatchNode *batch = [CCSpriteBatchNodebatchNodeWithFile:@"blocks.png" capacity:150]; [gameNode addChild:batch z:0 tag:0]; return self;}/* Our base collision handling routine */-(void) handleCollisionWithObjA:(GameObject*)objAwithObjB:(GameObject*)objB { //SENSOR to MISC collision if(objA.type == GO_TYPE_SENSOR && objB.type == GO_TYPE_MISC){  [self handleCollisionWithSensor:(GameSensor*)objAwithMisc:(GameMisc*)objB]; }else if(objA.type == GO_TYPE_MISC && objB.type == GO_TYPE_SENSOR){  [self handleCollisionWithSensor:(GameSensor*)objBwithMisc:(GameMisc*)objA]; } //MISC to MISC collision else if(objA.type == GO_TYPE_MISC && objB.type == GO_TYPE_MISC){  [self handleCollisionWithMisc:(GameMisc*)objA withMisc:(GameMisc*)objB]; }}/* Handling collision between specific types of objects */-(void) handleCollisionWithSensor:(GameSensor*)sensorwithMisc:(GameMisc*)misc { [message setString:@"Box collided with sensor"]; [self runAction:[CCSequence actions:[CCDelayTimeactionWithDuration:0.5f], [CCCallFunc actionWithTarget:self selector:@selector(resetMessage)], nil]];}-(void) handleCollisionWithMisc:(GameMisc*)a withMisc:(GameMisc*)b { [message setString:@"Box collided with another box"]; [self runAction:[CCSequence actions:[CCDelayTimeactionWithDuration:0.5f], [CCCallFunc actionWithTarget:self selector:@selector(resetMessage)], nil]];}/* Adding a new block */-(void) addNewObjectWithCoords:(CGPoint)p { /* CODE OMITTED */}- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { for( UITouch *touch in touches ) {  CGPoint location = [touch locationInView: [touch view]];  location = [[CCDirector sharedDirector] convertToGL: location];  [self addNewObjectWithCoords: location]; }}@end`

## How it works...

Here, we see the same block creation recipe from before except now a message is printed on the screen when either blocks collide with each other or they collide with a sensor.

• GameObject:
The GameObject class encapsulates Box2D data structures to help ease the process of Box2D object creation. It also includes a pointer back to its parent GameArea object as well as some other information we will use later. GameObject is intended to be an abstract base class that should be extended for specific uses.
• Sensors:
A fixture attached to a b2Body can be set to 'sensor mode'. This allows collision response routines to run without the body actually existing in the world physically. No physical collision response will occur. We've encapsulated this functionality in the GameSensor class. An object of this class can be differentiated from other objects by checking its type property.
• GameMisc:
The GameMisc class exists as an example of a typical extension of GameObject. The only added functionality in GameMisc is the life variable that we will use in later recipes.
• GameArea2D:
The GameArea2D class is where the action happens. Here, we encapsulate most of the functionality outlined in the previous recipe. In addition to that, we have an instance of DebugDrawNode and an instance of CCNode entitled gameNode. These allow us to draw our debug information and our game information separately from the main scene. This feature will come in handy as recipes become more complex.
• Contact listeners:
The class b2ContactListener is commonly overridden to allow for custom collision response handling. We extend b2ContentListener to create the basicContentListener class. There are four methods that can be extended to detect collision at a number of different intervals:
`void BeginContact(b2Contact* contact);void EndContact(b2Contact* contact);void PreSolve(b2Contact* contact, const b2Manifold* oldManifold);void PostSolve(b2Contact* contact, const b2ContactImpulse*impulse);`

The methods BeginContact and EndContact are fairly self-explanatory. The former is called when two fixtures begin to touch, the latter when they cease to touch. The PreSolve and PostSolve methods are called before and after the contact solver routine runs. For this recipe, we are only concerned with BeginContact. In this method, we retrieve two GameObject instances from body->GetUserData() and we pass them to the following method in the corresponding GameArea instance:

`-(void) handleCollisionWithObjA:(GameObject*)objAwithObjB:(GameObject*)objB;`

That method checks object types and finally displays different messages onscreen.

## There's more...

In this example, blocks are colliding with a static sensor. The sensor does not move because its body type attribute is set to b2_staticBody. Static bodies never move and they do not collide with each other. Each block has its type attribute set to b2_dynamicBody. Dynamic bodies move freely and collide with all other bodies.

## Cocos2d for iPhone 1 Game Development Cookbook

 Over 90 recipes for iOS 2D game development using cocos2d with this book and ebook
Published: December 2011
eBook Price: \$29.99
Book Price: \$49.99
See more

(For more resources on Cocos2d, see here.)

# Using different shapes

The primary attribute a Box2D body has is its shape. Box2D uses two classes, b2PolygonShape and b2CircleShape, to represent any possible shape. In this recipe, we will create a number of different shapes.

Please refer to the project RecipeCollection02 for full working code of this recipe.

## How to do it...

Execute the following code:

`@implementation Ch4_DifferentShapes/* Here add an object randomly chosen from a rectangle, square,circle, convex polygon and multi-fixture concave polygon. */-(void) addNewObjectWithCoords:(CGPoint)p{  //Initialize the object  GameMisc *obj = [[GameMisc alloc] init];  obj.gameArea = self;  obj.bodyDef->type = b2_dynamicBody;  obj.bodyDef->position.Set(p.x/PTM_RATIO, p.y/PTM_RATIO);  obj.bodyDef->userData = obj;  obj.body = world->CreateBody(obj.bodyDef);  obj.fixtureDef->density = 1.0f;  obj.fixtureDef->friction = 0.3f;  obj.fixtureDef->restitution = 0.2f;  //Pick a random shape, size and texture  int num = arc4random()%5;  if(num == 0){   /* Create square object */   /* CODE OMITTED */  //Create shape, add to fixture def and finally create the fixture  obj.polygonShape = new b2PolygonShape();  obj.polygonShape->SetAsBox(shapeSize/PTM_RATIO, shapeSize/PTM_RATIO);  obj.fixtureDef->shape = obj.polygonShape;  obj.body->CreateFixture(obj.fixtureDef);}else if(num == 1){  /* Create circle object */  /* CODE OMITTED */  //Create shape, add to fixture def and finally create the fixture  obj.circleShape = new b2CircleShape();  obj.circleShape->m_radius = shapeSize/PTM_RATIO;  obj.fixtureDef->shape = obj.circleShape;  obj.fixtureDef->restitution = 0.9f;  obj.body->CreateFixture(obj.fixtureDef);}else if(num == 2){  /* Create rectangle object */  /* CODE OMITTED */  //Create shape, add to fixture def and finally create the fixture  obj.polygonShape = new b2PolygonShape();  obj.polygonShape->SetAsBox(shapeSize.x/PTM_RATIO, shapeSize.y/PTM_RATIO);  obj.fixtureDef->shape = obj.polygonShape;  obj.body->CreateFixture(obj.fixtureDef);}else if(num == 3){  /* Create convex polygon object */  /* CODE OMITTED */  //Create shape, add to fixture def and finally create the fixture  obj.polygonShape = new b2PolygonShape();  obj.polygonShape->Set(vertices, numVerts);  obj.fixtureDef->shape = obj.polygonShape;  obj.body->CreateFixture(obj.fixtureDef);}else if(num == 4){  /* Create concave multi-fixture polygon */  /* CODE OMITTED */  //Create two opposite rectangles  for(int i=0; i<2; i++){   CGPoint shapeSize;   if(i == 0){ shapeSize = ccp(2.0f, 0.4f);   }else{ shapeSize = ccp(0.4f, 2.0f); }     CGPoint vertexArr[] = { ccp(0,0), ccp(shapeSize.x,0),ccp(shapeSize.x,shapeSize.y), ccp(0,shapeSize.y) };   int32 numVerts = 4;   b2Vec2 vertices[4];   NSMutableArray *vertexArray = [[[NSMutableArray alloc] init]autorelease];   //Set vertices   for(int i=0; i<numVerts; i++){   vertices[i].Set(vertexArr[i].x, vertexArr[i].y);   [vertexArray addObject:[NSValue valueWithCGPoint:ccp(vertexArr[i].x *PTM_RATIO, vertexArr[i].y*PTM_RATIO)]];  }  //Create textured polygon  ccTexParams params = {GL_NEAREST,GL_NEAREST_MIPMAP_NEAREST, GL_REPEAT,GL_REPEAT};  CCSprite *sprite = [TexturedPolygon createWithFile:@"box2.png"withVertices:vertexArray];  [sprite.texture setTexParameters:&params];  [sprite setPosition:ccp(0,0)];  [sprite setColor:color];  [obj.sprite addChild:sprite];  //Create shape, set shape and create fixture  obj.polygonShape = new b2PolygonShape();  obj.polygonShape->Set(vertices, numVerts);  obj.fixtureDef->shape = obj.polygonShape;  obj.body->CreateFixture(obj.fixtureDef);  } } //Set a random color [obj.sprite setColor:ccc3(arc4random()%255, arc4random()%255,arc4random()%255)];}- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { for( UITouch *touch in touches ) {  CGPoint location = [touch locationInView: [touch view]];  location = [[CCDirector sharedDirector] convertToGL: location];  [self addNewObjectWithCoords: location]; }}@end`

## How it works...

In this recipe, we randomly create objects with five different shapes: square, circle, rectangle, an oddly shaped convex polygon, and a simple concave polygon.

• Rectangles:
Rectangles are created using the b2PolygonShape method SetAsBox just like in the first two recipes. In this example, we have a simple textured square as well as a rectangular column image.
• Circles:
Circles are a special case in Box2D and they've been given a special class in b2CircleShape. After initialization, we simply set the m_radius variable of the circle shape. In this example, we also give the circle shaped objects a high restitution value to make them bounce. We will cover this in more depth in another recipe.
• Convex polygons:
Individual polygons must be convex. This means that every angle inside the polygon is less than 180 degrees. For this example, we've created an oddly shaped convex polygon with 8 vertices. We are using TexturedPolygon to accurately draw this polygon.
• Concave polygons:
Concave polygons can be represented by creating multiple convex polygons and linking them to one body using multiple fixtures. In this example, we link two simple convex polygons together by creating two fixtures on the same body. We reverse our width and height values to create a simple L-shaped object. With this technique, you can create arbitrarily complex shapes.
• Extensibility of GameObject:
The GameObject class is primarily designed for single fixture bodies. It contains one CCSprite object, one b2FixtureDef, and so on. However, as you can see in the concave polygon example, you can create multiple CCSprite objects and link them to the main GameObject sprite. You can also reuse the Box2D object pointers within the GameObject instance to easily create multiple fixtures and shapes.

# Dragging and collision filtering

In a previous recipe, we handled user input to allow the user to drag an object. In this example, we see a bowl filled with pieces of fruit that can be dragged across the screen. A piece of fruit does not collide with another piece of fruit.

Please refer to the project RecipeCollection02 for full working code of this recipe.

## How to do it...

Execute the following code:

`enum { //Collision bits for filtering CB_GROUND = 1<<0, CB_FRUIT = 1<<2, CB_BOWL = 1<<4};@implementation Ch4_DraggingAndFiltering-(CCLayer*) runRecipe { [super runRecipe]; [message setString:@"Pick up the fruit."]; //Create level boundaries [self addLevelBoundaries]; //Add fruit bowl [self addFruitBasket]; //Initialization of any variables fruitGrabbed = NO; return self;}/* Add basket and fruit objects */-(void) addFruitBasket { /* Add the basket */ /* CODE OMITTED */ //Add physical parts b2BodyDef bowlBodyDef; bowlBodyDef.position.Set(0, 0); bowlBodyDef.type = b2_staticBody; b2Body *body = world->CreateBody(&bowlBodyDef); b2PolygonShape bowlShape; b2FixtureDef bowlFixtureDef; bowlFixtureDef.restitution = 0.5f; bowlFixtureDef.filter.categoryBits = CB_BOWL; bowlFixtureDef.filter.maskBits = CB_FRUIT; //Rim left bowlShape.SetAsEdge(b2Vec2(120.0f/PTM_RATIO,120.0f/PTM_RATIO),b2Vec2(180.0f/PTM_RATIO,0.0f/PTM_RATIO)); bowlFixtureDef.shape = &bowlShape; body->CreateFixture(&bowlFixtureDef);/* CODE OMITTED */ /* Add fruit */ fruitObjects = [[[NSMutableArray alloc] init] autorelease]; [self addFruit:@"fruit_banana.png" position:ccp(210,200)shapeType:@"rect"]; [self addFruit:@"fruit_apple.png" position:ccp(230,200)shapeType:@"circle"]; [self addFruit:@"fruit_grapes.png" position:ccp(250,200)shapeType:@"rect"]; [self addFruit:@"fruit_orange.png" position:ccp(270,200)shapeType:@"circle"];}/* Add a fruit object with circle physical properties */-(void) addFruit:(NSString*)spriteFrame position:(CGPoint)pshapeType:(NSString*)s { //Create GameMisc object GameMisc *fruit = [[GameMisc alloc] init]; fruit.gameArea = self; //Define body def and create body fruit.bodyDef->type = b2_dynamicBody; fruit.bodyDef->position.Set(p.x/PTM_RATIO, p.y/PTM_RATIO); fruit.bodyDef->userData = fruit; fruit.body = world->CreateBody(fruit.bodyDef); //Create fixture def fruit.fixtureDef->density = 1.0f; fruit.fixtureDef->friction = 0.3f; fruit.fixtureDef->restitution = 0.4f; fruit.fixtureDef->filter.categoryBits = CB_FRUIT; fruit.fixtureDef->filter.maskBits = CB_GROUND | CB_BOWL; //Fruit does not collide with other fruit //Create sprite fruit.sprite = [CCSprite spriteWithSpriteFrameName:spriteFrame]; fruit.sprite.position = ccp(p.x,p.y); if([s isEqualToString:@"circle"]){  /* Set fixture shape and sprite scale */  float textureSize = 160;  float shapeSize = 40;  fruit.sprite.scale = shapeSize / textureSize * 2;  [gameNode addChild:fruit.sprite z:2];  fruit.circleShape = new b2CircleShape();  fruit.circleShape->m_radius = shapeSize/PTM_RATIO;  fruit.fixtureDef->shape = fruit.circleShape; }else if([s isEqualToString:@"rect"]){  /* Set fixture shape and sprite scale */  CGPoint textureSize = ccp(300,100);  CGPoint shapeSize = ccp(60,20);  fruit.sprite.scaleX = shapeSize.x / textureSize.x * 2;  fruit.sprite.scaleY = shapeSize.y / textureSize.y * 2;  [gameNode addChild:fruit.sprite z:2];  fruit.polygonShape = new b2PolygonShape();  fruit.polygonShape->SetAsBox(shapeSize.x/PTM_RATIO, shapeSize.y/PTM_RATIO);  fruit.fixtureDef->shape = fruit.polygonShape; }  //Finally create the fixture fruit.body->CreateFixture(fruit.fixtureDef); //Add object to container [fruitObjects addObject:fruit]; grabbedFruit = fruit;}-(void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; CGPoint point = [touch locationInView: [touch view]]; point = [[CCDirector sharedDirector] convertToGL: point]; /* Grab the nearest fruit */ //We first grab a fruit. //Then, if another fruit is closer we grab that until we finallyhave the closest one. float grabbedDistance = distanceBetweenPoints(point,ccp(grabbedFruit.body->GetPosition().x*PTM_RATIO, grabbedFruit.body->GetPosition().y*PTM_RATIO)); for(int i=0; i<fruitObjects.count; i++){  GameMisc *fruit = [fruitObjects objectAtIndex:i];  float thisDistance = distanceBetweenPoints(ccp(fruit.body->GetPosition().x*PTM_RATIO, fruit.body->GetPosition().y*PTM_RATIO),point);  if(thisDistance < grabbedDistance){   grabbedFruit = fruit;   grabbedDistance = thisDistance;  } } //Set the fruit to 'grabbed' fruitGrabbed = YES; //Immediately move the fruit [self ccTouchesMoved:touches withEvent:event];}-(void) ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; CGPoint point = [touch locationInView: [touch view]]; point = [[CCDirector sharedDirector] convertToGL: point]; /* Reposition the grabbed fruit */ grabbedFruit.body->SetTransform(b2Vec2(point.x/PTM_RATIO, point.y/PTM_RATIO), grabbedFruit.body->GetAngle()); b2Vec2 moveDistance = b2Vec2( (point.x/PTM_RATIO - grabbedFruit.sprite.position.x/PTM_RATIO), (point.y/PTM_RATIO - grabbedFruit.sprite.position.y/PTM_RATIO) ); lastFruitVelocity = b2Vec2(moveDistance.x*20, moveDistance.y*20);}-(void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { /* Release the fruit */ fruitGrabbed = NO; grabbedFruit.body->SetLinearVelocity(lastFruitVelocity);}-(void) step: (ccTime) dt { [super step:dt]; /* Suspend the fruit in mid-air while it is grabbed */ if(fruitGrabbed){  grabbedFruit.body->SetLinearVelocity(b2Vec2_zero); }}@end`

## How it works...

In this example, we create a realistic 'grabbing' effect. We achieve this by repositioning the nearest Box2D body with the SetTransform method:

`grabbedFruit.body->SetTransform(b2Vec2(point.x/PTM_RATIO, point.y/PTM_RATIO), grabbedFruit.body->GetAngle());`

We then store the previous distance the object was moved, to determine a final velocity and then to allow the object to be 'thrown' when the user lets go. We apply this velocity using the SetLinearVelocity method:

`grabbedFruit.body->SetLinearVelocity(lastFruitVelocity);`

To suspend fruit in the air while the user has a finger on the screen, we set the object's velocity to b2Vec2_zero while it is grabbed.

• Collision filtering:
In this example, we don't allow a fruit to collide with other fruits so that they can sit nicely in the bowl. We achieve this by setting the filter property on the fruit's fixture. Specifically, we set the categoryBits and maskBits:
`enum { CB_GROUND = 1<<0, CB_FRUIT = 1<<2, CB_BOWL = 1<<4};fruit.fixtureDef->filter.categoryBits = CB_FRUIT;fruit.fixtureDef->filter.maskBits = CB_GROUND | CB_BOWL;`

The categoryBits variable indicates what kind of object this is. The maskBits variable indicates what kind of objects this should collide with. Both of these properties use bits and Boolean logic to specify how the object should interact. For example, | means "or". So, we are saying that the CB_FRUIT category can collide with CB_GROUND or CB_BOWL categories. Alternatively, filters can be set using filter groups. Also note that, if you do not specify the fixture's filter variable on object then it will not collide with an object that has a set filter. For more information about filtering, please refer to the Box2D manual at: http://www.box2d.org/manual.html.

# Summary

In this article we covered the uses of the Box2D physics engine. Examples include debug drawing, collision response, different shapes, and dragging.

Further resources on this subject:

## Nathan Burba

Nathan Burba is a game developer, student, producer, and entrepreneur. He graduated from Ithaca College with a BA in Computer Science in 2008 and began working toward an MFA in Interactive Media at the University of Southern California School of Cinematic Arts in 2011. He founded Logical Extreme Studios LLC in 2011 and plans to release his first iOS game, Golden Age Baseball, in early 2012.