Search code examples
androidioscocos2d-xbox2d

Why do collisions behave differently in Android than in iOS?


I am using Box2D to simulate the physics world independently of my sprites, and I update the position of my sprites based on the position of b2body.

I have a player that consists of two fixtures. One fixture is not a sensor and can make contact with the ground. The other fixture is a sensor and is used to check for contacts with things like powerups eatables etc.

. I have some bodies (eatables, powers) in which the fixture consists of a single sensor that can make contact with the player sensor.

In iOS everything works fine - when the player collides with the powerup / eatable, he continues running as if nothing is wrong. But in Android he bounces off the powerup.

What could be the problem ? The plist file generated by physics editor is the same for both. Why should the simulation be different ? Box2d is part of cocos2d, so the library is the same and should be the same for both.

I am using cocos2d-x 3.7.

EDIT: I use the following:

ContactListener.h class:

class ContactListener : public b2ContactListener {

public:


    void BeginContact(b2Contact* contact) {
        void* bodyUserDataA = contact->GetFixtureA()->GetBody()->GetUserData();
        if (bodyUserDataA) {

        }
    }

    void EndContact(b2Contact* contact) {

    }
};

my ContactListener.cpp is empty.

Xcode automatically handles building everything properly and things "just work". On Android, I had to specify my cpp files in Application.mk, so I wonder whether this could cause some different behaviour, because I am not specifying the .h files anywhere.


Solution

  • This is due to a bug in GB2ShapeCache.cpp provided by the PhysicsEditor file. While the boolean check for isSensor works in iOS / OS X , in Android it doesn't work as expected and sets it to false instead of true.

    The fix:

    #if CC_TARGET_PLATFORM == CC_PLATFORM_IOS
                basicData.isSensor = (bool)static_cast<CCString *>(fixtureData->objectForKey("isSensor"))->intValue();
    #else
                CCString *foo = static_cast<CCString *>(fixtureData->objectForKey("isSensor"));
                const char *s = foo->getCString();
                if (s==NULL) {
                    basicData.isSensor = false;
                }else{
                    std::string str(s);
                    if (str=="true") {
                        basicData.isSensor = true;
                    }else{
                        basicData.isSensor = false;
                    }
                }
    #endif