post

Cocos2d Example – Box2d

Another excellent physics simulation library Box2d was integrated into Cocos2d 0.8 Beta. Box2d is written in C++, so if you are familiar with C++, Box2d may be a better choice than Chipmunk because of its object oriented design and interface. In addition, Box2d provides more detailed documentation than Chipmunk in its official website. In this tutorial, I will present how to use Box2d in Cocos2d by rewriting the Bouncing Ball example.

Step 1: Download Cocos2d 0.8 Beta project template from here. It should noted the installation method for 0.8 is slightly different from previous version because it introduces static linking. The project template will not include Cocos2d source codes any more. Instead, you need to add a Source Tree in xCode Preferences to point to the location where your Cocos2d library sits. Anyway, strictly follow the installation steps in the downloading page.

Step 2: Add Box2d Direct Dependency and Linked Library. By Default, the project template has already added Cocos2d and Chipmunk dependencies and Linked Libraries, but Box2d is not included. So you have to add it yourself. After you create a new project called Box2dBouncingBall, right click the Target Box2dBouncingBall, and select Get Info. You will see the following dialog.

In the screen shot above, we have added the box2d direct dependency and libbox2d.a library. If you don’t add the library correctly, you will get some linking errors during build.

Step 3: Add the ball image to Resources.

Step 4: Rename the implementation files Box2dBouncingBallAppDelegate.m and MyScene.m to Box2dBouncingBallAppDelegate.mm and MyScene.mm because you need to mix objective C and C++ codes together.

Step 5: Define PTM_RATIO constant. It’s equal to 32. This constant is used to convert pixel to Box2d unit. Add the line of code below to MyScene.mm.

@implementation MyScene

#define PTM_RATIO 32

Step 6: Add some instance variables to class MyScene.

#import <Foundation/Foundation.h>
#import “Scene.h”
#import “Box2D.h”
#import “Sprite.h”

@interface MyScene : Scene {
b2World* world; //world is similar to space in Chipmunk
b2Body* body; //body has the same meaning of body in Chipmunk

Sprite* ball;
}
@end

Step 7: Initialization. Update init function of MyScene class with the following codes:

-(id) init {
self = [super init];

if (self != nil) {
//Create sprite and add it to layer
ball = [Sprite spriteWithFile:@"ball.png"];
[ball setPosition:CGPointMake(150, 400)];
[self addChild:ball z:0];

//Create a world
CGSize screenSize = [Director sharedDirector].winSize;
b2AABB worldAABB;
float borderSize = 96/PTM_RATIO;
worldAABB.lowerBound.Set(-borderSize, -borderSize);
worldAABB.upperBound.Set(screenSize.width/PTM_RATIO+borderSize, screenSize.height/PTM_RATIO+borderSize);
b2Vec2 gravity(0.0f, -30.0f);
bool doSleep = true;
world = new b2World(worldAABB, gravity, doSleep);

//Create a ground box, the ground is defined as a rectangle.
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(screenSize.width/PTM_RATIO/2, -1.0f); //set with mid point, so /2
b2Body* groundBody = world->CreateBody(&groundBodyDef);
b2PolygonDef groundShapeDef;
groundShapeDef.SetAsBox(screenSize.width/PTM_RATIO/2, 1.0f);
groundBody->CreateShape(&groundShapeDef);

//Create ball body and shape
b2BodyDef ballBodyDef;
ballBodyDef.position.Set(150.0f/PTM_RATIO, 400.0f/PTM_RATIO);
ballBodyDef.userData = ball; //user data, will be used in world updating function

body = world->CreateBody(&ballBodyDef);
b2CircleDef ballShapeDef;
ballShapeDef.radius = 20.0f/PTM_RATIO; //radius
ballShapeDef.density = 1.0f; //density
ballShapeDef.friction = 0.3f; //friction
ballShapeDef.restitution = 0.5f; //elasticity
body->CreateShape(&ballShapeDef);
body->SetMassFromShapes(); //The function will help to calculate the mass

[self schedule:@selector(tick:)];
}
return self;
}

Step 8: World updating function.

-(void)tick:(ccTime) dt{
world->Step(dt, 10, 8);
for(b2Body* b = world->GetBodyList();b;b=b->GetNext())
{
if(b->GetUserData()!=NULL)
{

Sprite* ballData = (Sprite*)b->GetUserData();

ballData.position = CGPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO);
}
}
}

Step 9: Dealloc the resources.

-(void)dealloc{
delete world;
body = NULL;
world = NULL;
[super dealloc];
}

All right, these are the general steps when you are writing games using Box2d. For more details of some variables and functions, please refer to the Box2d documentation.

———————————–

Download: You can download the codes from here

Posted on 12th July 2009 in Uncategorized  •  No comments yet

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>