If you're new here, you may want to subscribe to my RSS feed or follow me on Twitter. Thanks for visiting!
This tutorial helps get you started with Box2D with Cocos2D by showing you how to create a simple app that shows a ball that you can bounce around the screen by rotating your iPhone with the accelerometer.
This tutorial is based on an excellent example by Kyle from iPhoneDev.net, but updated to Cocos2D 0.99.1-final and with some more detailed explanations of how things work. It also has some elements of the sample project that is included in the cocos2d-0.99.1 Box2d Application template, but explains how things work step-by-step.
This tutorial assumes that you’ve already gone through the tutorial on how to create a simple game with Cocos2D, or have equivalent knowledge.
So anyway, let’s get started learning Box2D with Cocos2D and start bouncing away!
Creating An Empty Project
Begin by creating a new project in XCode by selecting the cocos2d-0.99.1 Box2d Application template, and naming your project Box2D. If you compile and run this template, you’ll see a pretty cool example demonstrating many aspects of Box2D. However, for the purposes of this tutorial, we’re going to create everything from scratch so we can gain a good understanding of how things work.
So let’s clear out the template so we have a known-good starting point. Replace HelloWorldScene.h with the following:
#import "cocos2d.h" @interface HelloWorld : CCLayer { } + (id) scene; @end |
And replace HelloWorldScene.mm with the following:
#import "HelloWorldScene.h" @implementation HelloWorld + (id)scene { CCScene *scene = [CCScene node]; HelloWorld *layer = [HelloWorld node]; [scene addChild:layer]; return scene; } - (id)init { if ((self=[super init])) { } return self; } @end |
One last step – verify that all of your files in the Classes folder (such as HelloWorldScene) end with .mm instead of .m. If they end with .m, just rename them to .mm. We need to do this because Box2D uses C++ and this lets the compiler know that we’re about to start using C++ in this file.
If you compile and run that, you should see a blank screen. Ok great – now let’s start creating our Box2D scene.
The Box2D World In Theory
Before we go any further, let’s talk a bit about how things work in Box2D.
The first thing you need to do when using Cocos2D is to create a world object for Box2D. The world object is the main object in Cocos2D that manages all of the objects and the physics simulation.
Once we’ve created the world object, we need to add some bodies to the world. Bodies can be objects that move around in your game like ninja stars or monsters, but they can also be static bodies that don’t move such as platforms or walls.
There are a bunch of things you need to do to create a body – create a body definition, a body object, a shape, a fixture definition, and a fixture object. Here’s what all of these crazy things mean!
- You first create a body definition to specify initial properties of the body such as position or velocity.
- Once you set that up, you can use the world object to create a body object by specifying the body definition.
- You then create a shape representing the geometry you wish to simulate.
- You then create a fixture definition – you set the shape of the fixture definition to be the shape you created, and set other properties such as density or friction.
- Finally you can use the body object to create a fixture object by specifying the fixture definition.
- Note that you can add as many fixture objects to a single body object. This can come in handy when creating complex objects.
Once you’ve added all of the bodies you like to your world, Box2D can take over and do the simulation – as long as you call its “Step” function periodically so it has processing time.
But note that Box2D only updates its internal model of where objects are – if you’d like the Cocos2D sprites to update their position to be in the same location as the physics simulation, you’ll need to periodically update the position of the sprites as well.
Ok so now that we have a basic understanding of how things should work, let’s see it in code!
The Box2D World In Practice
Ok, before you begin download a picture of a ball I made that we’re going to add to the scene. Once you have it downloaded, drag it to the Resources folder in your project and make sure that “Copy items into destination group’s folder (if needed)” is checked.
Next, add the following to the top of your HelloWorldScene.mm:
#define PTM_RATIO 32.0 |
This is defining a ratio of pixels to “meters”. When you specify where bodies are in Cocos2D, you give it a set of units. Although you may consider using pixels, that would be a mistake. According to the Box2D manual, Box2D has been optimized to deal with units as small as 0.1 and as big as 10. So as far as length goes people generally tend to treat it as “meters” so 0.1 would be about teacup size and 10 would be about box size.
So we don’t want to pass pixels in, because even small objects would be 60×60 pixels, way bigger than the values Box2D has been optimized for. So we need to have a way to convert pixels to “meters”, hence we can just define a ratio like the above. So if we had a 64 pixel object, we could divide it by PTM_RATIO to get 2 “meters” that Box2D can deal with for physics simulation purposes.
Ok, now for the fun stuff. Add the following to the top of HelloWorldScene.h:
#import "Box2D.h" |
Also add member variables to your HelloWorld class:
b2World *_world; b2Body *_body; CCSprite *_ball; |
Then add the following to your init method in HelloWorldScene.mm:
CGSize winSize = [CCDirector sharedDirector].winSize; // Create sprite and add it to the layer _ball = [CCSprite spriteWithFile:@"Ball.jpg" rect:CGRectMake(0, 0, 52, 52)]; _ball.position = ccp(100, 100); [self addChild:_ball]; // Create a world b2Vec2 gravity = b2Vec2(0.0f, -30.0f); bool doSleep = true; _world = new b2World(gravity, doSleep); // Create edges around the entire screen b2BodyDef groundBodyDef; groundBodyDef.position.Set(0,0); b2Body *groundBody = _world->CreateBody(&groundBodyDef); b2PolygonShape groundBox; b2FixtureDef boxShapeDef; boxShapeDef.shape = &groundBox; groundBox.SetAsEdge(b2Vec2(0,0), b2Vec2(winSize.width/PTM_RATIO, 0)); groundBody->CreateFixture(&boxShapeDef); groundBox.SetAsEdge(b2Vec2(0,0), b2Vec2(0, winSize.height/PTM_RATIO)); groundBody->CreateFixture(&boxShapeDef); groundBox.SetAsEdge(b2Vec2(0, winSize.height/PTM_RATIO), b2Vec2(winSize.width/PTM_RATIO, winSize.height/PTM_RATIO)); groundBody->CreateFixture(&boxShapeDef); groundBox.SetAsEdge(b2Vec2(winSize.width/PTM_RATIO, winSize.height/PTM_RATIO), b2Vec2(winSize.width/PTM_RATIO, 0)); groundBody->CreateFixture(&boxShapeDef); // Create ball body and shape b2BodyDef ballBodyDef; ballBodyDef.type = b2_dynamicBody; ballBodyDef.position.Set(100/PTM_RATIO, 100/PTM_RATIO); ballBodyDef.userData = _ball; _body = _world->CreateBody(&ballBodyDef); b2CircleShape circle; circle.m_radius = 26.0/PTM_RATIO; b2FixtureDef ballShapeDef; ballShapeDef.shape = &circle; ballShapeDef.density = 1.0f; ballShapeDef.friction = 0.2f; ballShapeDef.restitution = 0.8f; _body->CreateFixture(&ballShapeDef); [self schedule:@selector(tick:)]; |
Phew, that was a lot of code. Let’s explain it bit by bit. I’ll repeat the code here section by section to make it easier to explain.
CGSize winSize = [CCDirector sharedDirector].winSize; // Create sprite and add it to the layer _ball = [CCSprite spriteWithFile:@"Ball.jpg" rect:CGRectMake(0, 0, 52, 52)]; _ball.position = ccp(100, 100); [self addChild:_ball]; |
First, we add the sprite to the scene just like we normally would using Cocos2D. If you’ve followed the previous Cocos2D tutorials there should be no surprises here.
// Create a world b2Vec2 gravity = b2Vec2(0.0f, -30.0f); bool doSleep = true; _world = new b2World(gravity, doSleep); |
Next, we create the world object. When we create this object, we need to specify an initial gravity vector. We set it here to -30 along the y axis, so bodies will appear to drop to the bottom of the screen. We also need to specify a value indicating whether or not objects should “sleep” once they are at rest. A sleeping object will not take up processing time until certain actions occur such as colliding with another object.
b2BodyDef groundBodyDef; groundBodyDef.position.Set(0,0); b2Body *groundBody = _world->CreateBody(&groundBodyDef); b2PolygonShape groundBox; b2FixtureDef boxShapeDef; boxShapeDef.shape = &groundBox; groundBox.SetAsEdge(b2Vec2(0,0), b2Vec2(winSize.width/PTM_RATIO, 0)); groundBody->CreateFixture(&boxShapeDef); groundBox.SetAsEdge(b2Vec2(0,0), b2Vec2(0, winSize.height/PTM_RATIO)); groundBody->CreateFixture(&boxShapeDef); groundBox.SetAsEdge(b2Vec2(0, winSize.height/PTM_RATIO), b2Vec2(winSize.width/PTM_RATIO, winSize.height/PTM_RATIO)); groundBody->CreateFixture(&boxShapeDef); groundBox.SetAsEdge(b2Vec2(winSize.width/PTM_RATIO, winSize.height/PTM_RATIO), b2Vec2(winSize.width/PTM_RATIO, 0)); groundBody->CreateFixture(&boxShapeDef); |
Next, we create invisible edges around the entire screen, that line up with the edges of our iPhone. We do this by performing the following steps:
- We first create a body definition and specify that the body should be positioned in the lower left corner.
- We then use the world object to create the body object.
- We then create a polygon shape for each edge of the screen. These “shapes” are actually just lines. Note that we have to convert the pixels into “meters” by using our conversion ratio as we discussed above.
- We create a fixture definition, specifying the polygon shape.
- We then use the body object to create a fixture object for each shape.
- Also note that one body object can contain multiple fixture objects!
// Create ball body and shape b2BodyDef ballBodyDef; ballBodyDef.type = b2_dynamicBody; ballBodyDef.position.Set(100/PTM_RATIO, 100/PTM_RATIO); ballBodyDef.userData = _ball; _body = _world->CreateBody(&ballBodyDef); b2CircleShape circle; circle.m_radius = 26.0/PTM_RATIO; b2FixtureDef ballShapeDef; ballShapeDef.shape = &circle; ballShapeDef.density = 1.0f; ballShapeDef.friction = 0.2f; ballShapeDef.restitution = 0.8f; _body->CreateFixture(&ballShapeDef); |
Next, we create the ball body. We do this by performing similar steps to how we created the ground body, but note the following differences:
- We specify the type as a dynamic body. The default value for bodies is to be a static body, which means it does not move and will not be simulated. Obviously we want our ball to be simulated!
- We set the user data parameter to be our ball CCSprite. You can set the user data parameter on a body to be anything you like, but usually it is quite convenient to set it to the sprite so you can access it in other places (such as when two bodies collide).
- We use a different shape this time – a circle shape.
- This time we want to set some parameters on the fixture, so we can’t use the shortcut method and need to specify the fixture definition. We’ll cover what the parameters mean later on.
[self schedule:@selector(tick:)]; |
The last thing in the method is to schedule a method named tick to be called as often as possible. Note that this isn’t the ideal way to do things – it’s better if the tick method is called at a set frequency (such as 60 times a second). However, for this tutorial we’re going to stay as-is.
So let’s write the tick method! Add this after your init method:
- (void)tick:(ccTime) dt { _world->Step(dt, 10, 10); for(b2Body *b = _world->GetBodyList(); b; b=b->GetNext()) { if (b->GetUserData() != NULL) { CCSprite *ballData = (CCSprite *)b->GetUserData(); ballData.position = ccp(b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO); ballData.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle()); } } } |
The first thing we do here is to call the “Step” function on the world so it can perform the physics simulation. The two parameters here are velocity iterations and position iterations – you should usually set these somewhere in the range of 8-10.
The next thing we do is make our sprites match the simulation. So we iterate through all of the bodies in the world looking for those with user data set. Once we find them, we know that the user data is a sprite (because we made it that way!), so we update the position and angle of the sprite to match the physics simulation.
One last thing to add – cleanup! Add this to the end of the file:
- (void)dealloc { delete _world; _body = NULL; _world = NULL; [super dealloc]; } |
Give it a compile and run, and you should see a ball drop down and bounce against the bottom of the screen a bit.
A Note On The Simulation
As promised let’s talk about those density, friction, and restitution variables that we set on the ball.
- Density is mass per unit volume. So the more dense an object is, the more mass it has, and the harder it is to move.
- Friction is a measure of how hard it is for objects to slide against each other. This should be in the range of 0 to 1. 0 means there is no friction, and 1 means there is a lot of friction.
- Restitution is a measure of how “bouncy” an object is. This should usually be in the range of 0 to 1. 0 means the object will not bounce, and 1 means the bounce is perfectly elastic, meaning it will bounce away with the same velocity that it impacted an object.
Feel free to play around with these values and see what difference it makes. Try to see if you can make your ball more bouncy!
Finishing Touches
It would be cool if we could get the ball to bounce around the screen as we tilt our device around. For one thing that will help us test that we’ve got all the boundaries working! This is quite easy to do. Add the following to your init method:
self.isAccelerometerEnabled = YES; |
Then add the following method somewhere in the file:
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration { // Landscape left values b2Vec2 gravity(-acceleration.y * 15, acceleration.x *15); _world->SetGravity(gravity); } |
All we’re doing here is setting the gravity vector in the simulation to be a multiple of the acceleration vector. Give it a compile and run (on your device), and you should be able to bounce your ball all around the screen!
Where To Go From Here?
Here’s a project with the all of the above code.
If you want to learn more about Box2D, check out my tutorial series on How To Create A Breakout Game with Box2D and Cocos2D!
Category: iPhone








Hi,
Thanks for this, its great. Can I ask – all the Box2D accelerometer demos change gravity. If you wanted to just apply a force to the object based on accelerometer inputs – so all the other Box2D objects dont begin to slide under gravity – is that easily achievable.
Great to have such clear Cocos demos…!
i
also, just to confirm – are co-ordinates of B2D objects anchored at bottom left, as I had thought they were centre anchored?
Yes, you can definitely make one object move with regard to the accelerometer input while the others remain in-place. All you have to do is use the ApplyForce on the body you want to move in the accelerometer:didAccelerate method, instead of calling SetGravity.
I whipped up a sample project that shows how to move just a single object based on accelerometer input that might help.
Sorry for not being clear about B2D coordinates. Yes when you set the position of a body object, you are setting where the center of the body object is.
So in the example of the ball object in the tutorial, we set the center of the Sprite to (100,100), and we set the center of the body object to (100/PTM_RATIO, 100/PTM_RATIO).
Remember that in Box2D the coordinates for the objects are really just a virtual space… it’s common to map the bottom left corner to Box2D (0,0) and the upper right corner to Box2D (winSize.width, winSize.height), but you could make other mappings if you need to for your game as well.
Hope this helps!
Hi,
Thats a great sample, thanks. When you are setting groundBodyDef.position.Set(0,0) in the example above (as you are setting up the edges of the screen) – how are these co-ordinates working in terms of centre anchored? Is this working differently because the shape is a line?
Regards
i
Hey Indy, ah yeah the way I understand it is when I call groundBodyDef.position.Set(0,0) that is setting the center of the ground body itself – but then when I add shapes (or edges) to the body their positions are relative to the position of the containing body.
So when I call AddEdge and specify the vertices of the edges, those positions should be relative to the center of the body (which is at 0,0).
Hi,
I think my confusion is how the box gets to be aligned to the extremities of the layer/screen, when the B2D co-ordinates are virtual.
i
Yeah, that can be confusing. There are two things that we use to make that happen. First we set up the following conversion:
Box2D coordinate = Cocos2D coordinate/PTM_RATIO
We know that the Cocos2D screen is bounded by the following points: (0,0) (0, winSize.width), (winSize.height, winSize.width), (winSize.height, 0).
So to make a border around the screen that objects will bounce off of, we just make an edge in Box2D coordinates that match up to exactly those screen coordinates, by using the conversion equation we defined above.
Hi,
I am probably over thinking it – but when you work with sprites, I understand setting a sprite at 0,0 – the position is in relation to the CCNode the sprite is contained in (CCLayer, CCSprite etc.). But Box2D has no knowledge of Cocos – so when setting something at (0,0) in Box2D – how does that align with the bottom left of the screen/CCNode (if that makes sense).
i
It’s because we use that conversion:
Box2D coordinate = Cocos2D coordinate/PTM_RATIO
So C2D(0,0) would be B2D (0/PTM_RATIO, 0/PTM_RATIO), which = (0,0).
In the tick method we go through each B2D object and use that equation to convert B2D coordinates to C2D coordinates.
If we wanted a different mapping, we’d just use a different equation. You could have B2D 0,0 be in the middle of the screen if you wanted by using the following:
Cocos2D X = Box2D X*PTM_RATIO + screensize.width
Cocos2D Y = Box2D Y*PTM_RATIO + screensize.height
I am not quite sure what is going on here, but I simply cannot compile the source code to my phone. I get 1804 errors regarding files that are in the libraries and it must be something simple that I am missing. I typically like to compile something before I work through the examples, to see what the end result is, but all of these examples are giving me trouble. They actually work fine in the simulator, but not when compiling to a device. I am trying to work through it, but cannot really find the answer yet…
Hm… so you downloaded the example project above and you’re getting errors while trying to compile? What do the errors look like? What version of the SDK are you using?
Hi Ray,
I too am getting the 1804 errors.
I’m running with the latest Xcode download, Snow Leopard, with cocos2d 0.99 and templates installed.
The simulator works fine, but as soon as I try, like Jared, on the device, Xcode chokes.
Any ideas?
Thanks
When I compile to the simulator it works fine and runs. When I compile to my phone I get 1804 errors, starting in b2BroadPhase.cpp, including errors like c++config.h not existing. What confuses me is the simulator running perfectly well. I am running the 3.2 sdk but am compiling to 3.1 for both simulator and device. I will keep plugging away at it, if you have an idea what it is that would be great, if not no worries.
Hm… two things I can think of to try: 1) make sure HelloWorldScene.mm ends with “.mm”, not “.m” (just realized I need to mention that in the tut), and 2) Expand Executables in your Groups & Files window, right click on your filename, and make sure “Set the working directory to: Build Products directory” is checked.
Either of those help?
No, that stuff was already good actually. I’ll try and figure it out. It has to be something unique to my machine for some reason, otherwise everyone would be having this problem. Thanks for the help!
So files like “bits/c++config.h” simply do not exist in my dev directories, but is apparently required by box2D. What do I need to be doing for my installs of XCode that are not done by default? The C++ directories are there, all the way down to the “bits” folder, but that c++config.h file isn’t there along with others that it needs…any idea? I will keep looking…
Got it. Set the gcc compiler to 4.0 instead of 4.2.
Awesome Jared, good to know!
Your cocos2d articles are *excellent* – many thanks!!
I do not have a development license to try this code on a physical device, so I am just using the simulator. Any attempt to use the Device|Rotate options does not do anything. Shouldn’t the ball fall? I even tried the default Box2d example and this does not react to the simulated accelerometer either. Am I missing something?
The 1804 or 1449 erros seems to becaused by the version of xcode beta 3.2 generates them but not the 3.1.3
@JamesR – Accelerometer support only works on physical devices, unfortunately!
If you want to test things out, you can just set the gravity vector yourself.
Another alternative is to just move onto the next tutorial (the Breakout game), where it doesn’t use the accelerometer at all.
Great tutorial Ray thanks!
I’ve tried to add an additional ball but the app crashes and I can’t figure out why. I’m adding the new circle like this:
- (void)createBall:(CGPoint)touchedAt{
CGSize winSize = [CCDirector sharedDirector].winSize;
_ball2 = [CCSprite spriteWithFile:@"ball3.jpg" rect:CGRectMake(0, 0, 52, 52)];
_ball2.position = ccp(touchedAt.x,touchedAt.y);
[self addChild:_ball2];
b2BodyDef ballBodyDef2;
ballBodyDef2.type = b2_dynamicBody;
ballBodyDef2.position.Set(100/PTM_RATIO, 100/PTM_RATIO);
ballBodyDef2.userData = _ball2;
_body2 = _world->CreateBody(&ballBodyDef2);
b2CircleShape circle;
circle.m_radius = 100;//(arc4random()*26.0)/PTM_RATIO;
b2FixtureDef ballShapeDef2;
ballShapeDef2.shape = &circle;
ballShapeDef2.density = 60.0f;
ballShapeDef2.friction = 0.2f;
ballShapeDef2.restitution = 0.8f;
_body2->CreateFixture(&ballShapeDef2);
}
Any suggestions much appreciated, I’ve been stuck on this for a while!
Thanks
Hey Alistair! I noticed a couple issues with the above code:
1) The radius of the box2d circle shape does not match the radius of the sprite (but it should). Since your sprite is 52×52, the radius of the circle should be 26 in Cocos2D coordinates, so 26/PTM_RATIO in Box2D coordinates (not 100). So you should have:
circle.m_radius = 26.0/PTM_RATIO;
2) The position you’re placing the box2d body does not mach the position of where you’re placing the sprite. You should have:
ballBodyDef2.position.Set(touchedAt.x/PTM_RATIO, touchedAt.y/PTM_RATIO);
I gave the above code with those mods a test and it seems to work OK now. Let me know how it goes!
Hi Ray-
Just a quick question, is there a reason you chose Box2D over Chipmunk for these examples? Or did you just pick one and “go for it”?
Hey Jared! I’m still new to Cocos2D so I haven’t played around with Chipmunk at all yet. When I was first looking into the differences between the two, I saw a lot of people saying that Chipmunk was slower between the two, so thought I’d give Box2D a try first.
Thanks for your response Ray, everything is working great now. I’m trying to implement drag functionality using the technique in this post: http://www.cocos2d-iphone.org/forum/topic/2298?replies=23#post-29087
though I’m not sure how I create the QueryCallback class. I’m going to have a look at your paddle game tutorial which looks like it will help.
Thanks again, your tutorials are great!
Just in case anyone else is having the same problem, I’ve figured this out and have updated the thread referenced in my last post.
I have a question,sometime the direction of the ball
will be horizontal for ever,the user can’t controll it
any more,how to detect the phenomenon and how to change the program code to solve it.
Thanks
@Mr ma: See my reply in the Breakout tutorial :]
Thanks again for another great tutorial. I think your shortcut of not using a b2FixtureDef may no longer exist.
error: no matching function for call to ‘b2Body::CreateFixture(b2PolygonShape*)’
libs/Box2D/Dynamics/b2Body.h:133: note: candidates are: b2Fixture* b2Body::CreateFixture(const b2FixtureDef*)
libs/Box2D/Dynamics/b2Body.h:142: note: b2Fixture* b2Body::CreateFixture(const b2Shape*, float32)
I amusing cocos2D v0.99.1
I changed your code to use a b2FixtureDef and it works perfectly:
// Create edges around the entire screen
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(0,0);
b2Body *groundBody = _world->CreateBody(&groundBodyDef);
b2PolygonShape groundBox;
groundBox.SetAsEdge(b2Vec2(0,0), b2Vec2(winSize.width/PTM_RATIO, 0));
b2FixtureDef boxShapeDef;
boxShapeDef.shape = &groundBox;
groundBody->CreateFixture(&boxShapeDef);
groundBox.SetAsEdge(b2Vec2(0,0), b2Vec2(0, winSize.height/PTM_RATIO));
boxShapeDef.shape = &groundBox;
groundBody->CreateFixture(&boxShapeDef);
groundBox.SetAsEdge(b2Vec2(0, winSize.height/PTM_RATIO),
b2Vec2(winSize.width/PTM_RATIO, winSize.height/PTM_RATIO));
boxShapeDef.shape = &groundBox;
groundBody->CreateFixture(&boxShapeDef);
groundBox.SetAsEdge(b2Vec2(winSize.width/PTM_RATIO,
winSize.height/PTM_RATIO), b2Vec2(winSize.width/PTM_RATIO, 0));
boxShapeDef.shape = &groundBox;
groundBody->CreateFixture(&boxShapeDef);
@Jason – Thanks, you’re right looks like the method must have been removed in the latest update. It looks like you can still create a fixture with a shape object if you pass the density as a second parameter. But I thought the tutorial would be more clear anyway without taking that shortcut, so I updated the tutorial and sample project to use the fixture definition method.
So it should now work with cocos2D 0.99.01, thanks for letting me know about this!
hi
was just checking my code and having a play around with it and for some reason the ball is more than elastic with the ballShapeDef.restitution = 1.0f, have tried it with 0.99f and even then it is more than elastic, was going to check this with your code but it doesnt appear to be downloadable, can you please reupload it
thanks
Many thanks! Just a quick question though. How would I give the body an initial velocity?
Thanks,
@Darc_pyro – Wow sorry for missing your comment all this time! Anyway I double checked the download and looks like it’s working OK.
@Arash – You can use something like the following:
Although I’m not actually sure if the point you should pass in should be a world coordinate or a local coordinate, if anyone knows lemme know O:-]
Fantastic tutorial, Ray. Thank you.
Also, I did some digging and found there is a way to get accelerometer data in the simulator. Go to the iTunes store and install the (free) accelerometer-simulator app on your iPhone/iPod. Follow the instructions under ‘info’ to get the data over a wifi network to the simulator.
http://itunes.apple.com/us/app/accelerometer-simulator/id336476721?mt=8#
Basically, you just need to add AccelerometerSimulation.m/h to the project and add #import “AccelerometerSimulation.h” immediately before #import “cocos2d.h” in HelloWorldScene.h.
You can even do it without an iPhone/iPod. Just look here.
http://blake.tsuhakofamily.com/2010/01/accelerometer-in-the-iphone-simulator/
Finally, change the code so the ball doesn’t sleep or once it does it won’t wake up again (without some code changes).
bool doSleep = false;
Mark
@Mark: Wow good to know, thanks!
Wonderful tutorials, I’m loving these. You should release a book, I’d pre-order it.
I can’t get the iPhone acceleromter sim working at all, I can’t afford to pay for my dev until next month, so I’ll just have to hope all the code I write works.
No doubt it’ll be 5 minutes of anticipation followed by 5 weeks of debug… ;)
Thanks Ray for this important tutorial. I have just one question that how we can set the range of ball movie not towards down but anywhere in the screen.
Look forward to hearing from you.
Thanks,
Surendra
@Andrew! Thanks! Hope testing goes well for you! :]
@Surendra: Sorry, but I’m not sure what you’re asking exactly…
Hi,
i want to move ball based on force from downside of ball like pool game so what should i do for it?
@Nandini: Check out ApplyImpulse for this.
Thanks Ray for tutorial.
It’s a great start with Box2D Game Development.
Just a question for you,
What is your preferred iPhone game engine to develop 3D games?
Thanks in advance.
@Jay: Haven’t made any 3D games yet so I am not sure! But I have heard good things about Unity.
Wonderful tuts, Ray!
Problem on a real device, though.
Works great on simulator but on device I get the following error:
Can’t install application
The Info.plist for application at /Users/Me/Desktop/Box2D/build/Debug-iphoneos/Box2D.app specifies device capability requirements, which are not met by My Iphone
My phone specs:
iPhone 3GS, 4.0 (8A293)
info.plist wasn’t changed.
Your animated bear & ninja tutorials work fine on actual device. Use of Box2D the issue?
Sorry for double post but I just unchecked LSRequiresIPhoneOS & UIStatusBarHidden in the Info.plist and it works fine now :-)
@JC: w00t! :]
I worked on some basic box2d code to add to the template for box2d and cocos2d, the app runs fine without it, but it crashed with it. No errors, it just crashes on launch :( any ideas?
Code:
CCSprite *myBox = [CCSprite spriteWithFile:@"blocks.jpg"];
[parentNode addChild:myBox];
myBox.position = ccp(230,160);
b2BodyDef myBoxDef;
myBoxDef.type = b2_dynamicBody;
myBoxDef.position.Set(myBox.position.x/PTM_RATIO,myBox.position.y/PTM_RATIO);
myBoxDef.userData = myBox;
b2Body *body = world->CreateBody(&myBoxDef);
b2PolygonShape myDynamicBox;
myDynamicBox.SetAsBox(1, 1);
b2FixtureDef myFixtureDef;
myFixtureDef.shape = &myDynamicBox;
myFixtureDef.density = 1.0f;
myFixtureDef.friction = 0.3f;
body->CreateFixture(&myFixtureDef);
YAY! Never mind I got it to work, It depended where I called the code in the method I was using, I had to do it after the gravity and walls and everything were set up :) Great Tutorial Thanks!
Hi, i am using the following code to draw a circular edge in scene.
// Create edges around the entire screen
b2BodyDef groundBodyDef;
//groundBodyDef.position.Set(0,0);
b2Body *groundBody = _world->CreateBody(&groundBodyDef);
b2PolygonShape groundBox;
b2FixtureDef boxShapeDef;
boxShapeDef.shape = &groundBox;
float angle;
float previousX;
float previousY;
float radius=50;
for(int i = 0; i CreateFixture(&boxShapeDef);
previousX=240 + (cos(angle) * radius)/PTM_RATIO;
previousY=120 + (sin(angle) * radius)/PTM_RATIO;
}
but i think the circular edge doesn’t create properly..
@Pierce: w00t glad you got it working!
@Rony: If you look at the “Edge Shapes” example in the Box2dTestBed that comes with Cocos2D you’ll see an example of how to do something similar to what you’re trying to do there.
Thanks a lot Ray, your tutorial is very useful to me.
Hi Ray thanks for your tutorial. they help me a lot on iphone developing bu I have a problem that how to control the moving of the body confuse me all the time.for example I want to use a meunItem to move the sprite left and right the object of cocos2d can be moved but the body I do not know how to Move it because they are simulated by the core of box2d
Hi Ray!
I have a question about basic programming theory and didn’t know where to ask, so anyone who knows can answer too! I am making a game using Box2D and I am having different levels in my game. But I will be using the same objects with the same properties throughout the entire game, such as walls, and i was wondering how you would organize the class of walls and change the location depending on the level. Thanks
@clint: Yeah the trick with Box2D is to move an object, you have to use Box2D methods like ApplyForce() and ApplyImpulse() instead of using the Cocos2D actions like MoveTo(), etc.
@Kyle: For that you’d probably want to make a “Wall” or “GameObject” class and use those from within your game scenes. It’s often useful to have a class like that hold pointers to your Box2D object and Cocos2D sprites for easy reference. I think there are several threads in the Cocos2D forums about this topic if you look around, I think I’ve stumbled across this in the past.
Ray !
Thanks for your help! :)
Hi Ray,
Great tutorial! I created and ran the tutorial in the simulator and it works, but when I run it on my iPhone, it runs for a few seconds and then freezes. I have OS 4.0.1 installed and have an iPhone 3G. I have my BAse SDK set to iPhone Device 4.0 and the iPhone OS Deployment Target set to iPhone OS 4.0. The XCODE SDK is version 3.2.3. Please advise. Thanks in advance. I get a message stating: GDB:Program Received Signal: “SIGABRT”
-Anant
@Anant: Here’s my general advice for how to diagnose a crash issue on iOS:
1) Set a breakpoint in the init method for your scene and step through until you narrow down where it’s crashing
2) Set the NSZombieEnabled argument in your executable options, which sometimes helps narrow down the cause
3) Run with Apple Instruments such as leaks to look for memory issues
4) Tried and true “comment out code till it works” then backtrack from there :]
And in this case, you can also compare your code to the sample project and try to see what is different as well!
Thanks so much Ray! This tutorial does a good job in actually understanding what everything does.
But one problem, when i compile the code i get no errors, but when i launch it, it starts up, shows the splash screen, then crashes.
It still crashes if i paste the code from the sample project into the template, from the helloworld.h/m files. But it works fine if i just compile the sample project. Would anybody have any idea what could be wrong? Thanks.
Sorry, didnt see above comment
After debuging for 5 hours, my crash problem was: I didn’t import “ball.jpg”
In the simulator everything works well, but when I try to run it on the device I receive this error: <> What could be wrong?
solved. i forgot to add the ball to resources. but it is still strange why it worked in the simulator.
Very, very nice! I’ve been looking for simple and straightforward tutorials for iPhone game development and this is the first time I actually understand an iPhone tutorial.
One question: Do you have any apps on the app store available for download?
@Spencer: Yep! You can see the list of apps I’ve developed at my company’s site, razeware.com.
Hi,
I ll fix the positions of few balls and only one ball has to rotate and fall down with gravity, can anyone help me out how to set the gravity for only one ball. If the moving ball hits other balls also they should not move.
can anyone suggest me how to do this please.
Is is possible to move a ball body to touch location by using method applyForce or ApplyLinearImpulse? Can you suggest me to do this?
Hi Ray,
For some reason, I’m getting 17 errors when you say I should compile it. First, it says that “ISO C++ forbids declaration of ‘b2world’ with no type”. Am I missing something? I’m pretty sure I typed in the code right.
Hello again Ray,
I’ve extended this excellent tut to a side scroller with lots of box2d bodies bounced around by a “stationary player”. The player is kept horizontally stationary by scrolling the scene with the camera. I’ve started trying to put in a HUD but of course the buttons move with the camera. I’ve been knocking my head around the web trying to grasp how it can be done with moving the layers but not much luck. I don’t use a tilemap at all (your other tut uses a tilemap but no box2d). Any hints on making this work?
@Lakshmikanth: It’s been a while since I’ve played around with Box2D, but I think you want to use static bodies for the balls so they don’t move rather than dynamic bodies.
@Siju: Don’t know offhand, why not use Mouse Joints, they’re made for moving objects with respect to touch movement…
@Chuck Norri… erm I mean Jim :]… Make sure the file has the extension “mm” at the end so XCode treats it as including C++ code.
@J: Most of the time people handle this by having a HUD on a different layer – is that what you’re doing?
Hi Ray,
I am very thankful to for such a great tutorial from u.
I have one question , how to spin paddle or rotate the paddle with infinite no of times.
Can u please help me in this regards, i am new to cocos2d and Box2d
@Anilkumar: Might want to check the Box2D forums for that, they’d be able to steer you on that better than I could.
Hey Ray,
I have setup the bouncing ball tutorial and made slight modifications to remove the right side and top boundaries. What I want is the ball to bounce and the camera/view to follow the ball
I have tried to use CCFollow using both the ball itself or just its position but it doesn’t work
any help?
Hey, Ray! Um.. I was wondering if it would be possible to make the balls not collide together if there are two balls on the screen but still bounces off the paddle(you know, like a power-up).
Thanks,
Wil.
@wil zh
You can use collision groups.
From box 2d manual:
http://www.box2d.org/manual.html#_Toc258082970
Collision groups let you specify an integral group index. You can have all fixtures with the same group index always collide (positive index) or never collide (negative index). Group indices are usually used for things that are somehow related, like the parts of a bicycle. In the following example, fixture1 and fixture2 always collide, but fixture3 and fixture4 never collide.
fixture1Def.filter.groupIndex = 2;
fixture2Def.filter.groupIndex = 2;
fixture3Def.filter.groupIndex = -8;
fixture4Def.filter.groupIndex = -8;
Collisions between fixtures of different group indices are filtered according the category and mask bits. In other words, group filtering has higher precedence than category filtering.
@Kav: I have some notes on getting the screen to follow an object in my tile map tutorial that may help:
http://www.raywenderlich.com/1163/how-to-make-a-tile-based-game-with-cocos2d
@indy: Thanks so much for helping out Wil! And good to see you again too haven’t heard from you in a while, how’s it going? :]
Hi Ray,
Still starting projects too hard to finish!! I think I need to just do something simple to go through the entire process and get something in the b****y app store!
Keep up the good work
i
@indy: Yeah it’s best to start small and work up from there! Keep at it and you’ll be in there before long! :]
trying to make an AI car steer itself…….
http://www.youtube.com/watch?v=iMOK9FpNBi4
hard….!
@ray just starting on some box2d work and your tutorials for them are just as awesome as the tile game series!
@Indy I know how you feel, it seems all I do is get stuck trying to create the “masterpiece”
Great tutorial, Ray :). This helped me make the decision between Box2d and chipmunk and will help jumpstart my game.
@indy: Nice, cool demo and artwork you’ve got there, looks like you’re having a lot of fun! :]
@Charlie: Thanks! Haha yep, when I get into that situation I remember a funny quote someone told me that helps me push it through: “It’s time to slap some lipstick on this pig and ship it!” ;]
@William: Cool, best of luck with your game! :]
@indy
I put the code into a scheduler that creates a new ball every 3 seconds. However, sadly, the balls are still colliding.
CGSize winSize = [CCDirector sharedDirector].winSize;
int randdiv = 10;
int rand = arc4random() %(randdiv+1);
int rand2 = (arc4random() %8) – 4;
// Create sprite and add it to the layer
CCSprite *ball = [CCSprite spriteWithFile:@"Ball.jpg" rect:CGRectMake(0, 0, 10, 10)];
ball.position = ccp((rand * winSize.width/randdiv )+rand2 , 100);
ball.tag = 1;
[self addChild:ball];
id actionFadeIn = [CCFadeIn actionWithDuration:1];
[ball runAction:[CCSequence actions:actionFadeIn, nil]];
// Create ball body
b2BodyDef ballBodyDef;
ballBodyDef.type = b2_dynamicBody;
ballBodyDef.position.Set(rand * winSize.width/randdiv/PTM_RATIO, 100/PTM_RATIO);
ballBodyDef.userData = ball;
b2Body *_ballBody = _world->CreateBody(&ballBodyDef);
// Create circle shape
b2CircleShape circle;
circle.m_radius = 5.0/PTM_RATIO;
// Create shape definition and add to body
b2FixtureDef ballShapeDef;
ballShapeDef.shape = &circle;
ballShapeDef.density = 1.0f;
ballShapeDef.friction = 0.0f; // We don’t want the ball to have friction!
ballShapeDef.restitution = 1.0f;
b2Fixture *_ballFixture = _ballBody->CreateFixture(&ballShapeDef);
// Give shape initial impulse…
b2Vec2 force = b2Vec2(arc4random() %100 / 2000 – 0.02, 1);
_ballBody->ApplyLinearImpulse(force, ballBodyDef.position);
[_balls addObject: ball];
colFilter = 1;
ballShapeDef.filter.groupIndex = colFilter;
Thanks!
~wil
you need to use a negative number to make things never collide, what you have done is made them always collide….try -1
You used [self schedule:@selector(tick:)]. You mentioned that that wasn’t really the way to go. 1, why? 2, what would you use? I high resolution timer?
thx
Ralph
Hey Ray I must say this was the best one can find on the web for cocos2d related learning ,Thanks for that !!!
But i have one question ,I am using a Xcode 3.2.4 installed in a different location and one more 3.2.2 installed in the developer folder.When i compile the template with the former on i get So many errors!!
Is there a flag that i need to use during installation of the templates to fix this Issue !!
Thanks A lot !!
in the box2d world,How to cause two or more balls still defers to the original direction to go forward after the collision
in the box2d world,How to cause two or more balls after mutual collides, still marched forward according to the original direction.
thanks
Is there a way to change the background color to something other than black? I tried to subclass CCColorLayer and add the following to the scene init method, but it still comes up black. Thanks.
if( (self=[super initWithColor:ccc4(0, 255, 255, 255)] )) {
@indy: Thanks for helping out @Wil!
@Wil: Also, you need to set the group index on the fixture def BEFORE you call CreateFixture.
@Ralph: In the latest version of Cocos2D, there’s a new method called scheduleUpdate that you can call on a node to have an update method called each and every frame. That’s what I use these days for code I want to run every frame.
@Prashant: Hm I use XCode 3.2.4 as well, and don’t have any issues. But yeah when installing the Cocos2D templates, the install_templates.sh script takes an argument so you can tell it where to install the templates.
@Mr ma: Why not just make them not collide with each other by setting collision filters, if you don’t want them to react to a collision with each other?
@jms: You’re on the right track. Instead of deriving from CCLayer, you should derive from CCColorLayer. I have an example in this tutorial:
http://www.raywenderlich.com/352/how-to-make-a-simple-iphone-game-with-cocos2d-tutorial
@Ray: Thanks for your quick response and all the tutorials. They are great!
I have tried deriving from CCColorLayer, but it’s not working. I should also mention that my project started from the Box2d template, so I’m wondering if that is the issue.
If you just create a new project using the template and change CCLayer to CCColorLayer and add the initWithColor it still remains black. Is there something different in how Box2d handles background colors? Thanks.
@jms: Ah that explains it. The problem is in the Box2D template, it overrides the draw method, but never calls [super draw]. But it’s necessary to call [super draw] for CCColorLayer to draw the background color, because that’s where the color is added. So simply add “[super draw];” to the end of your draw method and it should work :]
It’s a cool tutorial. Thanks to you. But I want to run two ball in the world and they colloid(collusion) each other in the world ? How can i make this ?
@mondal: You can add as many bodies as you want to a Box2D world – so simply create another body/fixture for the second ball and they will collide, etc.
Hi again Ray,
I was having a look at your Box2D tutorials and after searching around haven’t really been able to find an answer – (unless I am just being stupid!)
When we do:
b2CircleShape circle;
is there any way we can hide this actual shape? In the simulation, if the sprite isn’t larger than the b2CircleShape, then I can see a pink (awake) object or grey (sleeping) shape for each box2d object.
So how would be go about hiding these?
Umm…You can disable the GLdraw function.
Thank you Wil Zh, I knew it had to be something simple. I obviously didn’t read enough to realise that GLdraw was being used for that (should have noticed anyway seeing as though it definitely was not a sprite being used for the shapes) :)
First of all, congratulations on your blog, I have a couple of weeks following your tutorials and they are excellent.
I’m looking forward to buy your book when released, and i have a lot of expectations.
Once again congratulations!.
I’m new to Objective-C, but I have 10 years programming in Microsoft technologies, and I have a stupid question:
I’ve seen you declare variables with the symbol “_” in front, What does this symbol mean in Terms of programming?
Excuse my English, I’m Spanish.
Greetings.
P.D. I will make a donation as soon as i can, you deserve it!
@Stornu2: That underscore means nothing, it’s just a naming convention I like to use sometimes to help keep things straight. For more details, see my response to @Jason in this tutorial:
http://www.raywenderlich.com/1797/how-to-create-a-simple-iphone-app-tutorial-part-1
Dear Ray…
You Suck!! lol.. keep up the good work! When is the book dropping? and will it have box2d in it? when I was looking over the sample code it looked jus like regular cocos2d. i guess i answered my own question.
Awesome site, thanks for all your help!
However I found a problem that I’m not sure if it’s being caused by Cocos2d, Box2d, or even this tutorial… but if you compile this and run it on an iPhone (I have an iPhone 4 running 4.2) and you tilt it so that the accelerometer makes the ball go to any of the screen corners, once the ball stops bouncing it will FREEZE the ball in the corner, and then the iPhone has to be locked and then unlocked in order for it to be used again. The app will also stop working and will have to be deleted and re-installed on your phone.
I hope this makes some sense and you guys can recreate this scenario to see what I’m talking about.
Hey Ray,
Thanks for all your tutorials, they were really helpful and your response to commenters make you a great person.
Just want to know, let’s say I want to create a scenario where I’ll apply an impulse to throw the ball to the right, I’ll have the camera following the ball and I wont know when the ball will stop bouncing/rolling. Here’s a few questions:
1. What’s the best way to create a physics world for the above scenario when you wont know where is the end edge (limitless world)?
2. Using ApplyLinearForce I notice the ball would eventually roll, is it possible to just bounce the ball but not let it roll?
3. at certain Fixture definition (like the one posted aboce), the ball seem to bounce endlessly as if the ground is vibrating, did i miss something regarding that?
Hi Ray, awesome tutorial! I am making a game using Box2d and cocos2d. It is going to support the Retina display. In cocos2d they changed the position data (I don’t know how you call it) from pixels to points, however i don’t think they did that in box2d. How can i have PTM_RATIO = 64 for Retina display devices and how can i have PTM_RATIO = 32 for non-Retina display devices?
@Dexx: Yep the book has 3 chapters on Box2D. The first chapter is about making a very simple puzzle game with Box2D, and the second two chapters go onto some more advanced topics to make a cool cart racing game. You can check out a video and see details about when it’s coming out, etc. here:
http://www.raywenderlich.com/2274/cocos2d-book-and-360idev
@Adrian: Hm, weird. I don’t have time to look into this right now, but if you figure out the problem, let me know!
@KrashEd: Thanks for the kind words! In response to your questions:
1) You can either create a very very large world (that is unlikely for the user to ever reach), or you can write some code to check where the ball is, and dynamically keep adding ground pieces to the left and right of the ball as it moves, to give the illusion of an infinite floor.
2) One very simple way is to never change the rotation of the ball sprite. Another solution is set a very large angular damping on the sprite. There’s probably others too.
3) Not sure what you’re asking here?
@Josh: You should just work in points, not pixels, so PTM_RATIO would mean “points to meters ratio”.
Thanks For the response ray. I have another question. This is regarding the value for the gravity. In the tutorial you used -30.0 on the y value for gravity. Is that value in anyway related to the PTM_RATIO? IS there a way to calculate a realistic or at least functioning value for the gravity based on the PTM_RATIO?
sorry for double posting, while you may be answering my question I might as well ask. What is the proper way of repositioning the ball to a certain location (Let’s say resetting back to starting position)? I am currently doing it by destroying the body and recreating it using redefined b2BodyDef and b2FixtureDef, is there a more elegant way of doing it?
Hi Ray,
I wanted to say thank you! I started with this tutorial many months ago.
Combined with your other tutorials, many hours of late night coding/recoding, intense perseverance, and pure luck at times I was able to get my game North Pole Ninja approved for sale! It’s not going to break any records for sure but it is a start.
Your willingness to help others is a testimony to the spirit of what it means to be an independent developer. Your teaching style is excellent! Still saving my pennies to buy your book!
Happy Holidays!
-JC
@KrashEd – I think you can use the statement Yourb2Body->SetTransform(b2Vec2( YourPositionX, YourPositionY ), YourAngleToRotate); for immediate “teleporting” to new position.