Search code examples
androidbox2dcocos2d-android

Box2d Cocos2d Android gravity not working


I'm trying to create a simple test for Box2d, Cocos2d, and Android. All I need is to put one body on the screen, and have it respond to gravity. I looked everywhere and there are good tutorials for non-Android applications but none of them has gravity on Android working. Can anyone help?

This is the code I'm using. I took it, and modified lightly from here: http://www.expobrain.net/2012/05/12/box2d-physics-simulation-on-android/

For creating the world:

World world = new World(new Vec2(2.0f, 8.0f), false);

And this is how I create the body:

public void setupBallBody() {
    CGSize size = CCDirector.sharedDirector().winSize();
    CGPoint pos = CGPoint.make(size.width / 1.2f, size.height / 1.2f);

    // Create Dynamic Body
    BodyDef bodyDef = new BodyDef();

    bodyDef.type = BodyType.DYNAMIC;
    bodyDef.position.set(screenToWorld(pos));

    ballBody = world.createBody(bodyDef);
    MassData md = new MassData();
    md.mass = 5;
    ballBody.setMassData(md);        

    // Create Shape
    CircleShape ballShape = new CircleShape();

    ballShape.m_radius = SMILE_RADIUS;

    // Create fixture
    FixtureDef ballFixture = new FixtureDef();

    ballFixture.shape = ballShape;
    ballFixture.density = SMILE_DENSITY;
    ballFixture.friction = SMILE_FRICTION;
    ballFixture.restitution = SMILE_RESTITUTION;
    // Assign fixture to Body
    ballBody.createFixture(ballFixture);

    // Set sprite
    final CCSprite ballSprite = CCSprite.sprite("ball.jpg");
    ballSprite.setPosition(pos);
    addChild(ballSprite, 0);
    ballBody.setUserData(ballSprite);

}

This is my "tick" method (which I'm not sure is part of what makes gravity working but I include it here for completeness.)

public void tick(float dt) {
    synchronized (world) {
        world.step(1/60, 10, 10);
    }

    // Update sprites
    for (Body b = world.getBodyList(); b != null; b = b.getNext()) {

        if(b == ballBody) {
            CCSprite ballSprite = (CCSprite)ballBody.getUserData();
            if(ballSprite != null) {
                ballSprite.setPosition(worldToScreen(ballBody.getPosition())));     
                ballSprite.setRotation(-1.0f * (float)Math.toDegrees((ballBody.getAngle()))); 
            }
        }           
    }
}

Solution

  • My guessing here is this line may be the problem.-

    world.step(1/60, 10, 10);
    

    step function handles the bodies positions based on the time passed since last step. You're doing an integer division 1/60, which result is 0. Try 1.0f / 60.0f instead.

    Otherwise, you're telling your world that 0 milliseconds passed since the last step, so bodies will always remain at their initial position.

    However, it's not good practice to 'hardcode' your time step. You better pass to your world step the delta time your receiving.-

    world.step(dt, 10, 10);
    

    Also, you may simplify your loop to work for any body with an attached CCSprite, like this.-

    for (Body b = world.getBodyList(); b != null; b = b.getNext()) {
        CCSprite sprite = (CCSprite)b.getUserData();
        if(sprite != null) {
            sprite.setPosition(worldToScreen(b.getPosition())));     
            sprite.setRotation(-1.0f * (float)Math.toDegrees((b.getAngle()))); 
        }           
    }