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.png" 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.png" 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.png" 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.png"];
[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.png”
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.