Make a dynamic body static in Cocos2D

Make a dynamic body static in Cocos2D

April 23, 2014

Inspired by this interesting question on StackOverflow I want to show you a short example how to work with advanced physics features in Cocos2d 3.0. This will give you an idea of what can be done with the new integrated physics engine Chipmunk.

Q: How can I turn a dynamic physics body into a static body upon collision, to make the object stick to a surface?

1. Import a new header file

First of all it is important to know, that not all Chimpunk features are exposed through Cocos2d classes like CCPhysicsNode and CCPhysicsBody. For some more advanced features you need to use the actual Objective-Chipmunk API.

In Cocos2d 3.0 you need to import a special header to get access to the underlying Chipmunk objects contained in CCPhysicsNode and CCPhysicsBody:

#import "CCPhysics+ObjectiveChipmunk.h"

2. Add a post-step callback

As the StackOverflow question states, it is not simply possible to change the bodyType from dynamic to static in the collision handler. The problem is, that the collision handler is called while Chipmunk is calculating a physics step. During a calculation of a step collisions are resolved and objects are moved around. Chipmunk locks the Chipmunk Space of the CCPhysicsNode during this calculation because changing the body or removing objects while calculating the impact of collisions can result in unexpected behaviour.

You can however change the bodyType of a CCPhysicsNode after the step calculation completed. To do so you need to add a post-step callback. I have implemented this in a branch of our SpriteBuilder Tutorial:

- (void)ccPhysicsCollisionPostSolve:(CCPhysicsCollisionPair *)pair penguin:(CCNode *)penguin wildcard:(CCNode *)nodeB
    if (nodeB == _catapultArm) {
        // penguin shall not stick to catapultArm
    float energy = [pair totalKineticEnergy];
    // if energy is large enough, make penguin static
    if (_currentPenguin.launched && (energy > 10000.f))
        [[_physicsNode space] addPostStepBlock:^{
        penguin.physicsBody.type = CCPhysicsBodyTypeStatic;
    } key:penguin];

Whenever a penguin collides with a high velocity I turn it into a static physics body. The most interesting lines are these:

[[_physicsNode space] addPostStepBlock:^{
     penguin.physicsBody.type = CCPhysicsBodyTypeStatic;
} key:penguin];

Through the header we imported earlier we have access to the ChipmunkSpace of our physics node. This is where we add the postStepBlock. That block is executed when Chipmunk completed the step calculation. Within this block we change the type of the physics body to static.

The key value you pass into the callback is used to ensure that the callback is only called once. This is especially important when removing objects, but it also makes sense in this case, because we don't want to change the body type multiple times.

With this implementation penguins get stuck to surfaces (or in the air, when the ice blocks fall to the ground) when they collide intensely with other physics objects:

iOS simulator screen

You can check out the implementation on GitHub!

Happy coding!


If you have feedback on this tutorial or find any mistakes, please open issues on the GitHub Repository.

Join Make School Icon

Join Make School

Prepare for your career as a founder or software developer

Apply now
Talk to Us Icon

Talk to Us

If you have any questions, please send us an email.

Email Us