furyfish
furyfish

Reputation: 2135

Why my code can't detect collision between two dynamic bodies?

This is my code:

public class Physics3 extends ApplicationAdapter {

        SpriteBatch batch;
        Sprite sprite, sprite2;
        Texture img;
        World world;
        Body body, body2;
        Body bodyEdgeScreen;

        Matrix4 debugMatrix;
        OrthographicCamera camera;

    //    final float PIXELS_TO_METERS = 100f;

        final short PHYSICS_ENTITY = 0x1;    // 0001
        final short WORLD_ENTITY = 0x1 << 1; // 0010 or 0x2 in hex

        @Override
        public void create() {
            batch = new SpriteBatch();
            img = new Texture("badlogic.jpg");

            // Create two identical sprites slightly offset from each other vertically
            sprite = new Sprite(img);
            sprite.setPosition(-sprite.getWidth()/2,-sprite.getHeight()/2 +200);
            sprite2 = new Sprite(img);
            sprite2.setPosition(-sprite.getWidth()/2 + 20,-sprite.getHeight()/2 + 800);

            world = new World(new Vector2(0, -100f),true);

            // Sprite1's Physics body
            BodyDef bodyDef = new BodyDef();
            bodyDef.type = BodyDef.BodyType.DynamicBody;
            bodyDef.position.set(sprite.getX() + sprite.getWidth()/2,
                    sprite.getY() + sprite.getHeight()/2);

            body = world.createBody(bodyDef);


            // Sprite2's physics body
            BodyDef bodyDef2 = new BodyDef();
            bodyDef2.type = BodyDef.BodyType.DynamicBody;
            bodyDef2.position.set(sprite2.getX() + sprite2.getWidth()/2,
                    sprite2.getY() + sprite2.getHeight()/2);

            body2 = world.createBody(bodyDef2);

            // Both bodies have identical shape
            PolygonShape shape = new PolygonShape();
            shape.setAsBox(sprite.getWidth()/2, sprite.getHeight()/2);

            // Sprite1
            FixtureDef fixtureDef = new FixtureDef();
            fixtureDef.shape = shape;
            fixtureDef.density = 0.1f;
            fixtureDef.restitution = 0.5f;
            fixtureDef.filter.categoryBits = PHYSICS_ENTITY;
            fixtureDef.filter.maskBits = WORLD_ENTITY;

            // Sprite2
            FixtureDef fixtureDef2 = new FixtureDef();
            fixtureDef2.shape = shape;
            fixtureDef2.density = 0.1f;
            fixtureDef2.restitution = 0.5f;
            fixtureDef2.filter.categoryBits = PHYSICS_ENTITY;
            fixtureDef2.filter.maskBits = WORLD_ENTITY;

            body.createFixture(fixtureDef);
            body2.createFixture(fixtureDef2);

            shape.dispose();

            // Now the physics body of the bottom edge of the screen
            BodyDef bodyDef3 = new BodyDef();
            bodyDef3.type = BodyDef.BodyType.StaticBody;

            float w = Gdx.graphics.getWidth();
            float h = Gdx.graphics.getHeight();

            bodyDef3.position.set(0, 0);
            FixtureDef fixtureDef3 = new FixtureDef();
            fixtureDef3.filter.categoryBits = WORLD_ENTITY;
            fixtureDef3.filter.maskBits = PHYSICS_ENTITY;

            EdgeShape edgeShape = new EdgeShape();
            edgeShape.set(-w/2,-h/2,w/2,-h/2);
            fixtureDef3.shape = edgeShape;

            bodyEdgeScreen = world.createBody(bodyDef3);
            bodyEdgeScreen.createFixture(fixtureDef3);
            edgeShape.dispose();

            camera = new OrthographicCamera(Gdx.graphics.getWidth(),Gdx.graphics.getHeight());

            createContactListener();
        }

        @Override
        public void render() {

            camera.update();
            // Step the physics simulation forward at a rate of 60hz
            world.step(1f/60f, 6, 2);

            sprite.setPosition((body.getPosition().x) - sprite.getWidth()/2 ,
                    (body.getPosition().y) -sprite.getHeight()/2 );
            sprite.setRotation((float)Math.toDegrees(body2.getAngle()));

            sprite2.setPosition((body2.getPosition().x) - sprite2.getWidth()/2 ,
                    (body2.getPosition().y) -sprite2.getHeight()/2 );
            sprite2.setRotation((float)Math.toDegrees(body.getAngle()));

            Gdx.gl.glClearColor(1, 1, 1, 1);
            Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

            batch.setProjectionMatrix(camera.combined);
            batch.begin();

            batch.draw(sprite, sprite.getX(), sprite.getY(),sprite.getOriginX(), sprite.getOriginY(),
                    sprite.getWidth(), sprite.getHeight(), sprite.getScaleX(), sprite.getScaleY(), sprite.getRotation());
            batch.draw(sprite2, sprite2.getX(), sprite2.getY(),sprite2.getOriginX(), sprite2.getOriginY(),
                    sprite2.getWidth(), sprite2.getHeight(), sprite2.getScaleX(), sprite2.getScaleY(), sprite2.getRotation());
            batch.end();
        }

        @Override
        public void dispose() {
            img.dispose();
            world.dispose();
        }

        private void createContactListener() {

            world.setContactListener(new ContactListener() {

                @Override
                public void beginContact(Contact contact) {
                    // TODO Auto-generated method stub
                    Body bodyA = contact.getFixtureA().getBody();
                    Body bodyB = contact.getFixtureB().getBody();
                    Gdx.app.log("beginContact", "between " + bodyA.toString() + " and " + bodyB.toString());
                }

                @Override
                public void endContact(Contact contact) {
                    // TODO Auto-generated method stub
                    Body bodyA = contact.getFixtureA().getBody();
                    Body bodyB = contact.getFixtureB().getBody();
                    Gdx.app.log("endContact", "between " + bodyA.toString() + " and " + bodyB.toString());
                }

                @Override
                public void preSolve(Contact contact, Manifold oldManifold) {
                    // TODO Auto-generated method stub

                }

                @Override
                public void postSolve(Contact contact, ContactImpulse impulse) {
                    // TODO Auto-generated method stub

                }

            });
        }

}

And I have a question: Why this code cant detect contact between two dynamic bodies? It just can detect collision between a dynamic and a static body.

Upvotes: 0

Views: 108

Answers (1)

Robert P
Robert P

Reputation: 9803

This is the expected result, as you are filtering the collision between the dynamic bodies:

 fixtureDef2.filter.categoryBits = PHYSICS_ENTITY;
 fixtureDef2.filter.maskBits = WORLD_ENTITY;

This says, that the fixtureDef2 is a PHYSICS_ENTITY (categoryBits) and should collide with WORLD_ENTITY (maskBits). If you want it to collide with the PHYSICS_ENTITY to, you need to set the maskbits to PHYSICS_ENTITY | WORLD_ENTITY.
Basicly the collision filtering is done like this:

boolean collide = (filterA.maskBits & filterB.categoryBits) != 0 && (filterA.categoryBits & filterB.maskBits) != 0;

In your actual case this is:

0010 & 0001 != 0 && 0001 & 0010 != 0

which is false and therefore there is no collision.

Here you can read more about collision filtering.

Upvotes: 1

Related Questions