Cocos2d Example – Bouncing Ball
In this example, we will use Cocos2d and ChipMunk physics engine to implement a bouncing ball. A ball falls towards the ground because of the force of gravity. The basic idea of ChipMunk is that you define some physical objects (including bodies and shapes, but they are invisible) in the space, then ChipMunk will simulate what happens to these objects. You should setup a callback function to update these objects’ visual representation (e.g., a sprite created with image).
Step 1: Create a Cocos2d Application and name it with “BouncingBall”. We assume you have installed Cocos2d project template properly.

Step 2: Add this image to Resources Group.
Step 3: Define the class BallLayer, which is a subclass of Layer. The codes are shown below:
// BallLayer.h
#import “cocos2d.h”
#import “Layer.h”
#import “chipmunk.h”
@interface BallLayer : Layer {
Sprite* ballSprite;
cpSpace* space;
}
@end
// BallLayer.m
#import “BallLayer.h”
void updateShape(void* ptr, void* unused){
cpShape* shape = (cpShape*)ptr;
Sprite* sprite = shape->data;
if(sprite){
cpBody* body = shape->body;
[sprite setPosition:cpv(body->p.x, body->p.y)];
}
}
@implementation BallLayer
-(void)tick:(ccTime)dt{
cpSpaceStep(space, 1.0f/60.0f);
cpSpaceHashEach(space->activeShapes, &updateShape, nil);
}
-(void)setupChipmunk{
cpInitChipmunk();
space = cpSpaceNew();
space->gravity = cpv(0,-2000);
space->elasticIterations = 1;
[self schedule: @selector(tick:) interval: 1.0f/60.0f];
cpBody* ballBody = cpBodyNew(200.0, INFINITY);
ballBody->p = cpv(150, 400);
cpSpaceAddBody(space, ballBody);
cpShape* ballShape = cpCircleShapeNew(ballBody, 20.0, cpvzero);
ballShape->e = 0.8;
ballShape->u = 0.8;
ballShape->data = ballSprite;
ballShape->collision_type = 1;
cpSpaceAddShape(space, ballShape);
cpBody* floorBody = cpBodyNew(INFINITY, INFINITY);
floorBody->p = cpv(0, 0);
cpShape* floorShape = cpSegmentShapeNew(floorBody, cpv(0,0), cpv(320,0), 0);
floorShape->e = 0.5;
floorShape->u = 0.1;
floorShape->collision_type = 0;
cpSpaceAddStaticShape(space, floorShape);
}
-(id)init{
self = [super init];
if(nil != self){
ballSprite = [Sprite spriteWithFile:@"ball.png"];
[ballSprite setPosition:CGPointMake(150, 400)];
[self add:ballSprite];
[self setupChipmunk];
}
return self;
}
@end
In class BallLayer, we defined a pointer ballSprite to point to a ball sprite that is initialized in init method. We also defined a cpSpace pointer space which points to a ChipMunk space. In init method, we invoked setupChipmunk function to setup ChipMunk stuff.
In setupChipmunk method, we first created a Chipmunk space and assigned some paremeters. (Note: The parameter elasticIterations should be greater than 1 if you want the ball bounces off the ground). We uses schedule:interval: method to schedule a selector tick: with an interval time. tick: function will call cpSpaceStep to update the space. In addition, cpSpaceHashEach function will call updateShape on each active shape. You will have chance to update the sprite’s (i.e., the ball’s) position in updateShape function (updateShape function is the callback function we metioned at the begining of this tutorial).
Next, the ball’s body and shape are created. We add ball’s shape to the ChipMunk space. In this case, we used segment to describe the shape of the ground and set the thickness of segment to be 0. Because the ground doesn’t move, the function cpSpaceAddStaticShape is used to add the shape of ground to the space. (Note: You can adjust the elasticity value (i.e., parameter e) of ball and ground to determine how high the ball can bounce).
Step 4: The project template has created MyScene class by default. We need to make the following modifications:
// MyScene.h
#import
#import “Scene.h”
#import “BallLayer.h”
@interface MyScene : Scene {
BallLayer* ballLayer;
}
@property (nonatomic, retain) BallLayer* ballLayer;
@end
// MyScene.m
#import “MyScene.h”
@implementation MyScene
@synthesize ballLayer;
-(void)dealloc{
[ballLayer release];
[super dealloc];
}
-(id)init{
self = [super init];
if(nil != self){
BallLayer* layer = [[BallLayer alloc]init];
self.ballLayer = layer;
[layer release];
[self add:ballLayer];
}
return self;
}
@end
Step 5: In BouncingBallAppDelegate.m file, applicationDidFinishLaunching method, change the following code:
[director setLandscape:YES];
to
[director setLandscape:NO];
Build&Go. You will see the following result:

Update: You can download the sourcecodes from here. In addition, in the codes above, -> was not displayed properly, now fixed.

Could you post the source code. Tried running the example and got too many errors to list.
to demetriusb,
Now you can download the soucecode in the post. Thanks.
Many thanks for this demo. It serves as a great starting point for development. I placed several circular static shapes in the drop path of the ball, and the ball whizzes right past. Playing with the floorShape, I noticed there are values for r, gravity, and ball diameter where the ball will ‘miss’ the floor. I suspect that the collision gets missed during the position update.
Assuming I haven’t made a programming error, can you suggest ways I might get the ball to interact with a new obstacle? Is it just playing with the variables, or is there another principle involved?
Many thanks for your efforts.
to Tom,
I don’t know what’s going on with your codes, but I suggest you pay attention
to the time step of updating the space. In ChipMunk documents, “The number of iterations,
and the size of the time step determine the quality of the simulation.
More iterations, or smaller time steps increase the quality. ”
You can use the following code to adjust the time step and to see if it can solve your problem.
int steps = 2;
cpFloat dtime = dt/(cpFloat)steps;
for(int i=0; i<steps; i++){
cpSpaceStep(space, dtime);
}
Thanks! Great tutorial!
I tried to go a step further and define the ceiling and right/left screen bounds so a ball would stay on the screen. I did this for the ceiling but it doesn’t bounce the ball back – it just passes right through.
cpBody *ceilingBody = cpBodyNew(INFINITY, INFINITY);
ceilingBody->p = cpv(0, 320);
cpShape *ceilingShape = cpSegmentShapeNew(ceilingBody, cpv(0,320), cpv(480,320), 0);
ceilingShape->e = 0.5; //elasticity
ceilingShape->u = 0.0; //friction
ceilingShape->collision_type = 0;
cpSpaceAddStaticShape(space, ceilingShape);
any ideas on how to detect the screen boundaries better? the floor works great – per this tut and I did the same to define the left side & that works, but ceiling and right side do not.
Hi, good post. I have been wondering about this issue,so thanks for posting. I’ll definitely be coming back to your site.
Justin, are you working in portrait (as the tutorial) or in landscape (like most games)? I was having trouble also and learned that Chipmunk uses bottom left corner as (0,0) while the standard iPhone code uses top left corner as (0,0). To remedy this I had to rotate the gravity vector when using the accelerometer. I’m not sure if this is causing your problem.
To admin, thanks for the tutorials, they are very helpful. Keep up the good work!
So just making sure I’ve got this right. If I wanted to have several bouncing balls, I would take care of all the chipmunk setup in my app delegate and pass the space to the ballLayer class, add the sprite to the space in the class, then handle the updating in the app delegate.
That sound about right?
Hi
Really, This is great tutorial.
Please do keep updating…:)
Thanks…
This tutorial needs updating for cocos2d v0.8.2 and iPhone OS 3.1.2.
The following are my changes as the original code does not work in the latest iPhone OS 3.1.2.
In BallLayer.m:
- Change [self add:ballSprite] to [self addChild:ballSprite]
Also in MyScene.m:
- Change [self add:ballLayer] to [self addChild:ballLayer]
You can add the optional z-order like [self addChild:ballLayer z:0].
In BouncingBallAppDelegate.m:
This method [director setLandscape:YES] is deprecated in cocos2d v0.8.2.
Current version already provides in the template support for device orientation, like [[Director sharedDirector] setDeviceOrientation:CCDeviceOrientationPortrait].
The above changes made this tutorial work in cocos2d v0.8.2 and iPhone OS 3.1.2.
more changes are required to update to cocos2d version 0.9 or 0.99
- class names have changed, most now use prefix “CC”, for example “CCLayer” instead of “Layer”
Hi Lt_Ender,
Exactly, some APIs change, more features included. This post
just provides a basic idea.
Great tutorial and introduction.
One thing I found while messing around though was that if I “dropped” the ball from a greater height (500), the ball would pass right through the floor.
Is there any reason why this would happen?
Hi Guys,
It is one of the brilliant example I came across for Cocos2D, first of I am using 0.99, and I agree class names has been changed so I changed in this example, but somehow it seems there is no cpContact point in collision function anymore, and second thing I wanna know if anyone of you came across to move an static sprite by action and it never called collision function to the floor static bodies/shapes, even I defined separate collision type for them.
I am making a game where you have two balls one you control by accelerometer and second one I animate using random actions. Now when first ball touch any of the floor shape collision function gets called and I showed a little particle effects but when second ball which has static body touch the floor no collision function gets called.
Now I know I have to update static body position according to sprite, thats exactly I am doing like this:
cpSpaceHashEach(space->activeShapes, &updateShape, self);
cpSpaceHashEach(space->staticShapes, &updateStaticShap, self);
cpSpaceRehashStatic(space);
It seems a dead end to my game, any help would be extremely appreciative.
regards,
Shafiq
@Shafiq – could the problem be as simple as a typo? Probably not, but I thought I’d ask just in case – because this:
&updateStaticShap
looks like you might have meant:
&updateStaticShape
(with an “e” at the end)
this blog desperately needs some code-formatting love.