Search code examples
libgdxbox2d

libgdx box2d friction joint not working


I am trying to make a simple example using the friction joints of box2d. I have created a circle that can be controlled with the mouse or arrow keys. There is also a box which is meant to be pushed with the circle. The problem is that when I push the box it keeps moving forever. I have added an auxiliary static box so I can join both boxes with a friction joint to simulate top-down friction. But it doesn't work. Here is the code.

public class MyGdxGame extends ApplicationAdapter {

    Camera camera;
    int windowWidth, windowHeight;

    World physicsWorld;
    Box2DDebugRenderer debugRenderer;

    Body frictionerBox;

    Body boxBody;
    Body circleBody;

    @Override
    public void create () {
        camera = new OrthographicCamera(2, 2);

        Box2D.init();
        physicsWorld = new World(new Vector2(0, 0), true);
        debugRenderer = new Box2DDebugRenderer();

        // frictioner box
        BodyDef bDef = new BodyDef();
        bDef.type = BodyDef.BodyType.StaticBody;
        bDef.position.set(0, 0);
        frictionerBox = physicsWorld.createBody(bDef);
        PolygonShape fShape = new PolygonShape();
        fShape.setAsBox(10, 10);
        FixtureDef fixDef = new FixtureDef();
        fixDef.shape = fShape;
        fixDef.density = 1.f;
        fixDef.friction = 1.f;
        //Fixture fix =
            frictionerBox.createFixture(fixDef);

        // box
        bDef = new BodyDef();
        bDef.type = BodyDef.BodyType.DynamicBody;
        bDef.position.set(0, 50);
        boxBody = physicsWorld.createBody(bDef);
        PolygonShape bShape = new PolygonShape();
        bShape.setAsBox(25, 25);
        fixDef = new FixtureDef();
        fixDef.shape = bShape;
        fixDef.density = 1.f;
        fixDef.friction = 1.f;
        boxBody.createFixture(fixDef);

        // circle
        BodyDef cDef = new BodyDef();
        cDef.type = BodyDef.BodyType.DynamicBody;
        cDef.position.set(20, 20);
        circleBody = physicsWorld.createBody(cDef);
        CircleShape cShape = new CircleShape();
        cShape.setRadius(12);
        fixDef = new FixtureDef();
        fixDef.shape = cShape;
        fixDef.density = 1.f;
        circleBody.createFixture(fixDef);

        FrictionJointDef frictionJointDef = new FrictionJointDef();
        frictionJointDef.maxForce = 10;
        frictionJointDef.maxTorque = 10;
        frictionJointDef.initialize(frictionerBox, boxBody, new Vector2(0, 0));
        physicsWorld.createJoint(frictionJointDef);

        bShape.dispose();
        cShape.dispose();
        fShape.dispose();
    }

    @Override
    public void render () {       

        handleInput();

        physicsWorld.step(Gdx.graphics.getDeltaTime(), 6, 2);


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

        debugRenderer.render(physicsWorld, camera.combined);

    }


    @Override
    public void resize(int width, int height)
    {
        camera.viewportWidth = width;
        camera.viewportHeight = height;
        camera.update();
        windowWidth = width;
        windowHeight = height;
        System.out.println("resized");
    }

    private void handleInput()
    {
        final float ARROW_SPEED = 60.0f;
        final float MAX_SPEED = 200.f;
        final float MIN_SPEED = 20.f;
        float vx, vy;
        if(Gdx.input.isTouched() || Gdx.input.isButtonPressed(Input.Buttons.LEFT))
        {
            int tx = (Gdx.input.getX() - windowWidth/2);
            int ty = -Gdx.input.getY() + windowHeight/2;
            float cx = camera.position.x;
            float cy = camera.position.y;
            float px = circleBody.getPosition().x;
            float py = circleBody.getPosition().y;
            px = px - cx;
            py = py - cy;
            vx = tx - px;
            vy = ty - py;
            float speed = (float) Math.sqrt(vx*vx + vy*vy);
            if( speed > MAX_SPEED )
            {
                vx = (vx/speed) * MAX_SPEED;
                vy = (vy/speed) * MAX_SPEED;
            }
            if( speed > 0 && speed < MIN_SPEED )
            {
                vx = (vx/speed) * MIN_SPEED;
                vy = (vy/speed) * MIN_SPEED;
            }
        }

        else
        {
            vx = vy = 0;
            if(Gdx.input.isKeyPressed(Input.Keys.W))
            {
                vy += 1;
            }
            if(Gdx.input.isKeyPressed(Input.Keys.S))
            {
                vy -= 1;
            }
            if(Gdx.input.isKeyPressed(Input.Keys.A))
            {
                vx -= 1;
            }
            if(Gdx.input.isKeyPressed(Input.Keys.D))
            {
                vx += 1;
            }
            float speed = (float) Math.sqrt(vx*vx + vy*vy);
            if(speed > 0.f)
            {
                vx = (vx/speed) * ARROW_SPEED;
                vy = (vy/speed) * ARROW_SPEED;
            }
        }

        circleBody.setLinearVelocity(vx, vy);

    }

}

What am I doing wrong?


Solution

  • I figured it out. It seems that for the friction to be noticeable you have to set very high values to maxForce and maxTorque.

    frictionJointDef.maxForce = 1000000;
    frictionJointDef.maxTorque = 10000000;