Home > iPhone Development > Cocos2d Example – Box2d

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

Categories: iPhone Development
  1. Crazy Dev
    July 22nd, 2009 at 22:00 | #1

    Hi,

    Really your tutorials are very helpful to us, specially collision ball. I am also new to cocos2D and i need to implement pinball game, so i thought i will do using cocos2D and chipmunk. My first goal is to move all between edge to edge with proper collision force, but i didn’t find anything that how can i move ball between edge to edge. I tried your collision demo but i could not do. If you can help me in this goal then really it will be great help for me.

    Thanks,
    Crazy Dev.

  2. jbishop
    July 25th, 2009 at 12:28 | #2

    Dependency & Linking Step:
    Could you elaborate on step 2? I cannot seem to get box2d to link properly. I have added the dependency by clicking the ‘+’ and selecting box2d, and have built and added the library manually and by dragging from the reference in the project to the link step in the target. So far, no luck. Any reference to box2d results in errors.

    I am using cocos2d-iphone-0.8-rc2

    Any help would be greatly appreciated! Thanks!

  3. jbishop
    July 26th, 2009 at 08:46 | #3

    After removing the references to chipmunk, things worked fine. Although the build generates 54 warnings; is that normal?

  4. admin
    July 28th, 2009 at 02:18 | #4

    Hi jbishop,

    I just added a post about project template installation.

  5. xhan
    July 28th, 2009 at 19:38 | #5

    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.

    I am not sure what PTM_RATIO means about , could you explain me more ?
    Thanks .

  6. admin
    July 28th, 2009 at 20:12 | #6

    hi xhan,

    Box2d uses meter as the unit, but iPhone uses pixel as the unit. Therefore, we need a scaling factor to convert the number of pixels to the number of meters. For example, the width of our screen is 320 pixels. If we select 32 as the scaling factor, the width will be 320/32=10 meters. With the same example, if you select a scaling factor larger than 32, you will find the falling time becomes shorter because the distance is shorter. You can have a try.
    BTW, You should select appropriate scaling factor according to your game. Based on the Box2d document, “You should try to get your moving objects in the range 0.1 – 10 meters”.

  7. Eric Safern
    August 3rd, 2009 at 12:52 | #7

    Hi,

    My link and build seem to go fine – but at runtime I get this exception message:

    Dyld Error Message:
    Symbol not found: _CFXMLNodeGetInfoPtr
    Referenced from: /System/Library/Frameworks/Security.framework/Versions/A/Security
    Expected in: /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.0.sdk/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation

    Any idea why?

    AFAIK, I’m running the latest versions of Xcode, Mac OS X, cocos2d and box2d.

  8. admin
    August 4th, 2009 at 00:05 | #8

    Hi Eric, I tried to build the project with the latest version of iPhone sdk and cocos2d, I met the same problem
    you mentioned. This should be a bug of the Cocos2d 0.8 Beta project template.

    I Created a new project template for Cocos2d 0.8 latest version and recreated the project
    in this article. No crash happened.
    You can download the new project template from here and new bouncingball project from
    here.

  9. jbishop
    August 4th, 2009 at 08:30 | #9

    Thanks again for the great tutorials. I was reading through the box2d docs though, and was unable to find a reference to the third parameter in world->step ().

    http://linuxuser.at/elements/doc/box2d/classb2_world.htm#8acc8d13cf764d1c80536eb84465d49e

    What does the third parameter refer to?

    Thanks!

  10. admin
    August 4th, 2009 at 14:15 | #10

    @jbishop
    Hi, you can jump to the definition of this function in xcode.

    /// Take a time step. This performs collision detection, integration,
    /// and constraint solution.
    /// @param timeStep the amount of time to simulate, this should not vary.
    /// @param velocityIterations for the velocity constraint solver.
    /// @param positionIterations for the position constraint solver.
    void Step(float32 timeStep, int32 velocityIterations, int32 positionIterations);

  11. jbishop
    August 4th, 2009 at 21:45 | #11

    I’m pretty new to xcode so i was looking to the internet for docs; sorry about that. Thank you!

  12. iphonemobdev
    August 13th, 2009 at 21:08 | #12

    Hi,

    Your tutorial is great. I learned a lot from your code.
    Now i have one problem. I am trying to implement pinball fllipper in my game but i am getting exact PTM_RATIO, Every time it crashes. How can i give exact PTM_RATIO for my game. I tried to give 1, 2, 5, 10, 20, 32, 50 but not useful. Following is the my vertex coordinates.

    shapeDef.vertices[0].Set(-30.0f/PTM_RATIO, -2.0f/PTM_RATIO);
    shapeDef.vertices[1].Set(-33.0f/PTM_RATIO, 0);
    shapeDef.vertices[2].Set(-30.0f/PTM_RATIO, -2.0f/PTM_RATIO);
    shapeDef.vertices[3].Set(30.0f/PTM_RATIO, 5.0f/PTM_RATIO);
    shapeDef.vertices[4].Set(30.0f/PTM_RATIO, -5.0f/PTM_RATIO);

    and my sprite size is (66, 46) and position is (182, 260) and i am getting following error,
    [Session started at 2009-08-14 09:25:52 +0530.]
    Assertion failed: (area > 1.19209290e-7F), function ComputeCentroid, file /Developer/Library/cocos2d-iphone-0.8/external/Box2d/Source/Collision/Shapes/b2PolygonShape.cpp, line 85.

    Do you have any idea that where i am wrong.

    Thanks.

  13. admin
    August 13th, 2009 at 21:55 | #13

    @iphonemobdev
    It seems that the vertex coordinates of your polygon are wrong. Why does the third
    vertex have the same position with the first one?

  14. iphonemobdev
    August 14th, 2009 at 03:51 | #14

    Hi Thanks for reply.

    I re corrected and again i tried it is not working and i changed order also but it is not working still.
    Is there any other things where i a wrong?.

    Thanks,
    Haresh.

  15. admin
    August 14th, 2009 at 04:30 | #15

    @iphonemobdev
    could you send me the codes? then I can have a quick look.

  16. iphonemobdev
    August 14th, 2009 at 05:22 | #16

    Yes, can you give me your email address on iphonemobdev@gmail.com? Thanks for great help.

  17. admin
    August 15th, 2009 at 03:27 | #17

    @iphonemobdev
    Hi, email sent. You can also find my email from the About page.

  18. June 3rd, 2010 at 20:54 | #18

    Thanks for the wonderful tutorial! That is very generous of you to provide help to the community!

    I am stuck and hoping you could help. How would you scroll or move the entire world? For example, if I set my world to be the size of four iPhone screens and want to allow the user to drag the scene around and interact with it, how could this be done? I am having a tough time finding any useful info in the Box2D documentation.


    Nick Vellios
    http://www.Vellios.com
    iPhone Development Resource

  19. June 3rd, 2010 at 20:55 | #19

    P.S. just a snippet on how to set the coordinates of the world would be plenty. I could then implement it myself. I just can’t find any code to do this and can’t decipher it from the Box2D Testbed within Cocos2d.


    Nick Vellios
    http://www.Vellios.com
    iPhone Development Resource

  1. July 13th, 2009 at 17:55 | #1
  2. July 23rd, 2009 at 04:08 | #2
  3. July 27th, 2009 at 19:51 | #3
  4. August 5th, 2009 at 22:30 | #4
  5. February 19th, 2010 at 00:03 | #5