Search code examples
ioscocos2d-iphonebox2dcollision-detection

Box2D bodies moving for no reason?


I am using Box2D with Cocos2D in my app. So pretty much in my app I make the bodies follow my CCSprites even though people recommend against it. Also I only use Box2D for collision detection so I just attach a body to my sprites and use a b2ContactListener and nothing else. Anyway this setup works for the most part except this little issue.

So my bodies follow my sprites like this in the game loop:

for(b2Body *b = world->GetBodyList(); b; b=b->GetNext()) {
        if (b->GetUserData() != NULL) {
            CCSprite *sprite = (CCSprite *)b->GetUserData();
                b2Vec2 b2Position = b2Vec2(sprite.position.x/PTM_RATIO, sprite.position.y/PTM_RATIO);
                float32 b2Angle = -1 * CC_DEGREES_TO_RADIANS(sprite.rotation);
                b->SetTransform(b2Position, b2Angle);
        }
    }

Also I create my b2World like this (if it makes any difference):

world = new b2World(b2Vec2(0.0f, 0.0f));
world->SetAllowSleeping(NO);
_contactListener = new MyContactListener();
world->SetContactListener(_contactListener); 

This issue is, whenever my CCSprites collide (technically my b2Bodys are colliding too), the b2Body on each CCSprite seems to move a bit as if a tiny force just hit it so they have a "recoil" if that makes sense. They move farther away from each other when the hit occurs even though no forces are involved.

Another example is when one of my bodies sits on top of another body, the body that is being stood on seems to tilt a bit when I am on the edge of it which is odd because I don't tilt my sprites.

Lastly, my bodies seem to be a bit behind on where the sprite is at that exact moment and I am not sure if that is also related to this issue but anyway is there any reason why this would be happening? Is there any way to make it so the bodies are not affected by forces and are solely used for collisions?

Thanks!


Solution

  • I believe that the bodies are triggering a collision response upon collision, which causes them to momentarily move apart a little, before snapping back into position when you force their b2transforms to sync with the sprite's positions/angles in the next game tick.

    Since you are using Box2D purely for collision detection, did you set the isSensor property of your fixture definition to true?

    b2FixtureDef shapeDef;
    shapeDef.isSensor = true;
    

    By specially marking the fixture as a sensor, it will never physically collide with anything, but you will still be notified when an overlap of bodies occur, via the contact listener.