+Box2D +libgdx How to Move EdgeShapes ?

Hi Guys!

Heres my problem, I have a game and this game uses box2d and libgdx.

I have an orthographic camera.
I have a player that can move to right and left and up/down.

The borders of the camera are blocked with edge shapes. So the player cannot pass the borders.

As a fact, the camera only moves on the .y Axis.
The player dont go out of the camera view.


I start the game by setting 3 edge Shapes.

Left wall
Right Wall
Bottom || ground

Problem : As the camera Moves up, how can i move the Shapes with me?

Codes :

At the Start:

/**
         * Add walls
         */
        /**
         * left side
         */
        leftShape = new EdgeShape();
        // bottom left
        Vector2 bottomLeft = viewport.unproject(new Vector2(0, Gdx.graphics.getHeight()));
        // top left
        Vector2 topLeft = viewport.unproject(new Vector2());
        leftShape.set(bottomLeft, topLeft);

        /**
         * right side
         */
        rightShape = new EdgeShape();

        // bottom right
        Vector2 bottomRight = viewport.unproject(new Vector2(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()));

        // top right
        Vector2 topRight = viewport.unproject(new Vector2(Gdx.graphics.getWidth(), 0));

        rightShape.set(bottomRight, topRight);

        /**
         * Bottom Wall
         */
        bottomShape = new EdgeShape();
        bottomShape.set(bottomRight, bottomLeft);

        //Walls Friction and restitution
        float wallFriction = 1f;
        float wallRestitution = 0.1f;

        Filter wallFilter = new Filter();
        wallFilter.categoryBits = CollisionLogic.getCATERGORY_WALLS();
        wallFilter.maskBits = CollisionLogic.getMASK_WALLS();

        /**
         * Bottom Wall
         */
        BodyDef bottomWallDef = new BodyDef();
        ground = world.createBody(bottomWallDef);

        Fixture bottomWallFixture = ground.createFixture(bottomShape, 1f);
        bottomWallFixture.setFriction(wallFriction);
        bottomWallFixture.setRestitution(wallRestitution);
        bottomWallFixture.setFilterData(wallFilter);

        /**
         * Left wall
         */
        BodyDef leftWall = new BodyDef();

        leftBodyWall = world.createBody(leftWall);

        Fixture leftWallFixture = leftBodyWall.createFixture(leftShape, 1f);
        leftWallFixture.setFriction(wallFriction);
        leftWallFixture.setRestitution(wallRestitution);
        leftWallFixture.setFilterData(wallFilter);

        /**
         * Right Wall
         */
        BodyDef rightWall = new BodyDef();

        rightBodyWall = world.createBody(rightWall);

        Fixture rightWallFixture = rightBodyWall.createFixture(rightShape, 1f);
        rightWallFixture.setFriction(wallFriction);
        rightWallFixture.setRestitution(wallRestitution);
        rightWallFixture.setFilterData(wallFilter);

I tried this : but i think i shouldnt use * PTM ( pixels to meter)

   private void updateWalls() {

        /**
         * Left Side
         */
        Vector2 bottomLeft = viewport.unproject(new Vector2(0, viewport.getScreenHeight() + viewport.getCamera().position.y));

        leftBodyWall.setTransform(bottomLeft.x * PTM, bottomLeft.y * PTM, 0);
        /**
         * Right side
         */
        Vector2 bottomRight = viewport.unproject(new Vector2(Gdx.graphics.getWidth(), Gdx.graphics.getHeight() + viewport.getCamera().position.y));

        rightBodyWall.setTransform(bottomRight.x * PTM, bottomRight.y * PTM, 0);

        /**
         * Bottom/Ground
         */
        bottomShape.set(bottomRight, bottomLeft);
        ground.setTransform(bottomLeft.x * PTM, bottomLeft.y * PTM, 0);

    }

EXTRA CODE :

  • THe camera.position.y is a test only!
 @Override
    public void render(float delta) {
        Gdx.gl.glClearColor(0, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        /**
         * Update
         */
        stage.act(delta);

        player.update(delta);
        updateWalls();
        /**
         * Update Box2D World
         */
        world.step(1 / 60f, 6, 4);

        int w = background.getWidth();
        int h = background.getHeight();
        float y = viewport.getCamera().position.y += 0 * (delta * 1);
        viewport.getCamera().update();

        batch.setProjectionMatrix(viewport.getCamera().combined);
        batch.begin();
        int repeat = (int) viewport.getWorldHeight() / h + 2;
        batch.draw(background, -viewport.getWorldWidth() / 2, -viewport.getWorldHeight() / 2 + h * (int) (y / h) * PTM, w * PTM, h * repeat * PTM, 0, repeat, 1, 0);
        Box2DSprite.draw(batch, world);

        for (SmokeEffect smoke : smokeEffects) {
            smoke.update(delta);
            smoke.render(batch);
        }

        batch.end();

        /**
         * Render Box2D World
         */
        renderer.render(world, viewport.getCamera().combined);

        stage.draw();

        for (Body body : removeBodies) {
            body.getWorld().destroyBody(body);
            removeBodies.removeValue(body, true);
        }

    }

    @Override
    public void resize(int width, int height) {
        viewport.update(width, height);
        stage.getViewport().update(width, height, true);
    }

I made a change and i got some weird results :

    private void printVector(Vector2 v) {
        System.out.println("(" + v.x + ";" + v.y + ")");
        v = viewport.project(v);
        System.out.println(" projected : (" + v.x + ";" + v.y + ")\n");

    }

    private void updateWalls() {

        Vector2 auxV = new Vector2();
        System.out.println("\nLeft Wall");

        leftShape.getVertex0(auxV);
        printVector(auxV);

        leftShape.getVertex1(auxV);
        printVector(auxV);

        leftShape.getVertex2(auxV);
        printVector(auxV);

        leftShape.getVertex3(auxV);
        printVector(auxV);

        System.out.println("\nRight Wall");

        rightShape.getVertex0(auxV);
        printVector(auxV);

        rightShape.getVertex1(auxV);
        printVector(auxV);

        rightShape.getVertex2(auxV);
        printVector(auxV);

        rightShape.getVertex3(auxV);
        printVector(auxV);

    }

it prints this :

Left Wall
(0.0;0.0)
projected : (400.0;300.0)

(-13.333334;-10.033335)
projected : (0.0;-1.0000348)

(-13.333334;9.966667)
projected : (0.0;599.0)

(0.0;0.0)
projected : (400.0;300.0)

Right Wall
(0.0;0.0)
projected : (400.0;300.0)

(13.333334;-10.033335)
projected : (800.0;-1.0000348)

(13.333334;9.966667)
projected : (800.0;599.0)

(0.0;0.0)
projected : (400.0;300.0)

it forms a triangle ? why? i mean its a line!

Ditch all the projection code. Make things simpler.

Create a fixed viewport with a virtual width/height, or a dynamic viewport that takes the width/height of the screen divided by some scale factor.

This means you can literlaly just specify the positions of things in world space, rather than having to swap in and out of projections constantly.

Secondly, what is the problem exactly? You have not really specified a problem in the OP but then say there is one in the second post. Do you want to move the shapes with you? Or are they being created as weird triangles?

For the record I would not move the left and right border with you, simply create new ones the higher/lower you get and remove ones that could never be interacted with.


[b]Player ascending:[/b]

| < new wall
| < new wall
| player
| < old wall
| < old wall

| < new wall
| < new wall
| player
| < old wall
| < old wall
| < way below the player, delete this one

[b]Player descending:[/b]

| < old wall
| < old wall
| player
| < new wall
| < new wall

| < old wall, way above the player, delete this one
| < old wall
| < old wall
|  player
| < new wall
| < new wall

Or if worlds have a fixed size, just make them span bottom to top and be done with it.

Thanks!
I solved another way though…
after a lot of debug and a lucky google random word search…

leftBodyWall.setTransform(0, viewport.getCamera().position.y, 0);

Works perfectly!

I will do the same with the other walls!

Thanks for the reply!