Box2D Driven Cocos2D Animation

15 Dec

One of the cool things about iSoccer is that it is a 2D game with the illusion of a 3D ball rolling around your iPad.  This is done by animating the CCSprite then varying animation speed and direction based on the speed and direction of the underlying Box2D object.

To follow along with this tutorial download the complete project from here and run it up in Xcode.  The starting point of this project was from the final code of the Box2D Swipe Interaction tutorial.  Here is what the project should look like when running in the simulator.  Swipe the ball to kick it around and it should animate nicely.

Animating a CCSprite

To animate the ball I used a sprite-sheet created with TexturePacker.  The sprite-sheet was created from 120 images taken from a 3D modelling program.  Every frame moved 3 degrees around the ball.  Look in the setupBallSprites method to see how to import the sprite-sheet. To load the sprites into memory I simply iterate through each of them and pop them into an array called rollFrames.

The code to animate sprites is pretty basic.  If you want to alter speed later then you must ensure you have a CCSpeed in there too.  I use rollFrames to create the CCAnimation, animate with CCAnimate, ensure the animation repeats forever with CCRepeatForever then finally ensure I can set the speed by wrapping the whole lot with CCSpeed.

speedAction =
[CCSpeed actionWithAction:
[CCRepeatForever actionWithAction:
[CCAnimate actionWithAnimation:
[CCAnimation animationWithFrames:rollFrames delay:0.1]]] speed:3.5];

Determining Trajectory

Cocos2D+Box2D physics simulations already change the position and rotation of a CCSprite based on the physics body that is tied to it.  You can see that in the stock standard Cocos2D+Box2D template code within the tick method:

//Synchronize the AtlasSprites position and rotation with the corresponding body
CCSprite *myActor = (CCSprite*)b->GetUserData();
myActor.position = CGPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO);
myActor.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle());

The rotation of the Box2D body being a 2D shape was not in keeping with the direction that the circle was traveling (because there is no Z axis).  In order to achieve the illusion of a rolling ball I had to force the sprite rotation to the direction of the trajectory.  Look in the tick method of the file and you will see this code:

// -- Rotation --
if (original.x != myActor.position.x && original.y != myActor.position.y){
CGFloat angleInRadians = atan2f(myActor.position.x - original.x, myActor.position.y - original.y);
CGFloat angleInDegrees = CC_RADIANS_TO_DEGREES(angleInRadians) + 90 + 180; // cocos2d 90 = radians 0
myActor.rotation = angleInDegrees;
original = myActor.position;

I determine the trajectory of the circle by drawing a line from the previous location (original) to the new position and calculating direction from that via atan2f.

Determining Speed

The speed of the animation had to match the speed of the body movement in order to show a convincing rolling ball.  This really just came down to a tuning exercise.  Play around with the values for yourself and see the interesting results.  Note that I capped the rolling speed at 8.

// -- Rolling Speed --
float32 speed = b->GetLinearVelocity().Length();
if (speed > 8) {speed = 8;}
[speedAction setSpeed:speed * 3.5]; // the multiplier tunes the animation so it matches the roll speed

As a bit of a bug fix I also force stop the Box2D body if it is moving too slowly. It didn’t look realistic otherwise .. it looked like the soccer ball was rolling on ice!

// -- Stop very slow rolls --
if (speed > 0.4) { b->SetLinearVelocity(b2Vec2(0.0, 0.0));
[speedAction setSpeed:0];

That’s it!

If you liked this tutorial or found something wrong with it please let me know!

If you want to support my work and have an iPad please consider purchasing iSoccer *wink*


Go to the Tutorials Index

Be Sociable, Share!

    About Tim Roadley

    I'm a Technical Solutions Architect at Park Assist (TKH Group). My current focus is the design and implementation of a Network Operations Centre (NOC) for Westfield (Scentre Group). Prior experience includes successful design and implementation of custom business intelligence dashboards for Westpac and a payments switch for Cuscal (RediATM). My current skill set includes solution architecture, business analysis, stakeholder management, project management, consulting, software development, IT infrastructure management and technical documentation. I've published a book on Core Data through Pearson Education, which you can find on Amazon by searching for my name. An updated version on this book is targeted for release before the end of 2016. I have several apps on Apple's App Store, including Teamwork, iSoccer, Grocery Dude (Objective-C) and now Groceries (Swift). In my down time I enjoy spending time with my wonderful wife Tracey and two lovely children Tyler and Taliah.

    Posted by on December 15, 2011 in iOS Tutorials


    22 Responses to Box2D Driven Cocos2D Animation

    1. leon

      December 16, 2011 at 2:28 am

      Tim, Thank you for the tutorial and a detail explanation. This is really useful for people like me that’s trying to figure out how the pros are doing it.

    2. Adrian

      December 20, 2011 at 2:22 pm

      Once again a gem of tutorial man. Great work and very helpful. I have a question though. I used cocos2d installer to install the templates on Xcode not the traditional way through terminal. I saw that you ported your project to Xcode with ios 5. Any idea how I can port my projects to ios 5?

      I tried to uninstall through terminal but it didn’t work. And have tried ray’s way on porting and refracting a sample project but libraries that I add through cocos2d iOS project show as red and refracting won’t work. Can you let me know how you ported yours please?

      Thanks again for a great tutorial.:)


    3. Junaid

      February 7, 2012 at 12:45 pm

      This is Awesome!. I have one question though which I am having a very hard time doing with this example. What if I want the ball to move to the direction where I did a touchend. If I touch the screen and lift my finger how do you get the ball to travel to that direction? I don’t want to kick the ball I want it to come to me only when i lift the finger.

      I have been scratching my head over this and cannot seem to figure out how to do this the right way. if you could post some code changes to this example that would be wonderful.

      Thank you so much!

      • Junaid

        February 7, 2012 at 2:22 pm

        I figured it out!! Here is the code for anyone else who might be interested in this type of feature. You modify the code in ccTouchesEnded only. You can change the impulse variable to how much force you want.

                if (swipe != NULL) {
                    for (b2Body* b = world->GetBodyList(); b; b = b->GetNext())
                        if (b->GetUserData() != NULL) {
                            CCSprite *myActor = (CCSprite*)b->GetUserData();
                            myActor.position = CGPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO);
                            if (myActor.tag == isTheBall) {
                                CGPoint direction = ccpSub(touchLocation,myActor.position);
                                direction = ccpNormalize(direction);
                                CGPoint impulse = ccpMult(direction, 5.0f);
                                b2Vec2 impulse_b2 = b2Vec2(impulse.x,impulse.y);
                    if (swipe.mouseJoint) {[swipe destroyMouseJointInWorld:world];} 
                    [swipe destroyBodyInWorld:world];
                    [swipe removeFromParentAndCleanup:YES];
                    swipe = nil;
    4. Huwell

      February 24, 2012 at 3:11 pm

      Hi Tim,
      Which 3D modelling program do you use? The football animation is perfect. I want to use a good tool to create a ball for my game. Can you help me?

      • Tim Roadley

        February 24, 2012 at 4:36 pm

        I used Daz Studio then captured each frame as an image. I rotated the ball 3 degrees then captured another image etc etc 120 times to get the 360 degree rotation.

        From my 120 images I then used texture packer to make a sprite sheet from them

        Hope this helps

    5. Huwell

      February 24, 2012 at 11:34 pm

      Thank you, Tim. I have found Photoshop CS5 can help me to finish it. Thanks again.

    6. Kiran

      March 13, 2012 at 4:40 pm

      Hi Tim,

      Awesome stuff!!.

      I am implementing similar behavior but using Coremotion Mananger a

    7. Kiran

      March 13, 2012 at 4:41 pm

      Hi Tim,

      Awesome stuff!!.

      I am implementing similar behavior but using Coremotion Mananger so ball will move based on device motions.

      any thoughts of guidance on that ?


      • Tim Roadley

        March 14, 2012 at 9:03 pm

        Shouldn’t be too difficult to implement, I’d just create a mousejoint to a cgpoint that varies with the tilt of the device.

        • Kiran

          March 19, 2012 at 2:07 pm

          Hi Tim,

          thanks for your input. I am able to implement the ball rolling on motions but I am getting ball jerking effects when i change device upside down. ball jerks while rotating and moving to another direction.

          how can i make it smooth ?

          thanks in advance.

    8. Tim Roadley

      March 19, 2012 at 2:21 pm

      I don’t know that you can as you only have control over 2 axis’ of rotation (x, y) you don’t have the z-axis as this is 2D. I was never able to get the rotation smooth.

    9. Kiran

      March 19, 2012 at 3:58 pm

      ok. thanks for quick reply.

    10. Kiran

      March 20, 2012 at 2:07 pm

      Hi Tim, what if we increased the images in spritesheet ? use 180 images instead of 120 will it help ?

      Reason I am so eagerly looking for this answer coz its the only loophole in whole animation otherwise its a awesome approach, but just due to this single issue i might have to give up this solution, hence i am trying hard to get some workaround for this jerkiness in animation .


      • Tim Roadley

        March 20, 2012 at 6:42 pm


        Unfortunately I don’t think that will help.

        When a 2d shape changes direction it changes the direction the circle that represents the ball is facing. This ‘lag’ is just how 2d shapes change direction and smoothing the transition to the ball from say rolling from 45 degrees to 80 degrees would look even more unnatural.

        You can see by my iSoccer game that I never solved this. If you can I am definitely all ears!!!



    11. vaseem

      May 22, 2012 at 4:11 pm

      HI TIm,
      I want to make a billiard ball but i m confuse there is a specific sequence to capture frame.I m confuse if i drop images to image texture it will create random frame sequence.If u will tell me exact procedure i will be very thankful to you

    12. Brian

      November 28, 2012 at 9:11 pm

      Hi Tim, marvellous example and it works beautifully but I’m having problems getting the animation to run smoothly using cocos2d v2.

      It only seems to happen when I update the speed property of the CCSpeed action in the tick function. If the speed property is constant this doesn’t seem to happen and the animation plays and loops seamlessly.

      I just wondered if you’d had any experience with version 2 or had any pointers about what might have changed to make the ball animation appear jerky?

    13. mick

      December 25, 2012 at 3:07 pm

      Thanks for this,

      I have been playing with spriteHelper and physics editor. And coming up short for implementing collision detection using box2d, sprite tracing with a program, and finally having an animation with collision detection — hopefully this will help me suss everything all out now.

    14. vel

      January 5, 2013 at 8:48 am

      Him Tim, Thanks for the great tutorial.

      I have something related, that I can’t solve. I want to be able to slightly deform the ball on the side it was hit on. Everywhere I search it says that box2d supports only rigid bodies, but this should be doable. Any ideas on this?

    15. Jonathon

      January 2, 2014 at 3:29 pm

      Nice tutorial, thanks!

      var e = document.getElementById(“entry-author-info”);
      var s;
      s = ”;
      e.innerHTML = s;


    Leave a Reply

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