1
\$\begingroup\$

I'm trying to draw a ChainShape according to touch screen coordinates, however the coordinates are slightly off from my touch coordinates. I translate the chain drawn on the screen to world coordinates but don't think I've done it correctly.

I tried setting the shape's position to the first vertex but it positions it even further from the original touch coordinates. Can someone please help me understand where I'm going wrong?

public class Play implements Screen {
    private static final float TIMESTEP = 1 / 60f;
    private static final int VELOCITYITERATIONS = 8, POSITIONITERATIONS = 3;

    private Box2DDebugRenderer debugRenderer;
    private OrthographicCamera camera;
    private PolygonSpriteBatch batch;
    private World world;

    private List<Float> chain_verts = new ArrayList<Float>();
    private float[] chain;

    @Override
    public void show() {
        world = new World(new Vector2(0f, -9.81f), true);
        debugRenderer = new Box2DDebugRenderer();
        camera = new OrthographicCamera();
        batch  = new PolygonSpriteBatch();

        InputProcessor input_0 = new GestureDetector(new Gesture() {
        }) {
            @Override
            public boolean touchUp(float x, float y, int pointer, int button) {
                if (chain_verts.size() != 0) {
                    chain = new float[chain_verts.size()];
                }

                for (int i = 0; i < chain_verts.size(); i++) {
                    chain[i] = chain_verts.get(i);
                    System.out.print(chain[i] + " ");
                }

                ChainShape chainShape = new ChainShape();
                chainShape.createChain(chain);

                Vector3 mouse = new Vector3();
                camera.unproject(mouse.set(Gdx.input.getX(), Gdx.input.getY(), 0));

                BodyDef bodyDef = new BodyDef();
                bodyDef.type = BodyType.StaticBody;
                bodyDef.position.set(mouse.x , mouse.y);

                FixtureDef fixtureDef = new FixtureDef();
                fixtureDef.shape = chainShape;

                world.createBody(bodyDef).createFixture(fixtureDef);

                chain_verts.clear();
                chainShape.dispose();

                return super.touchUp(x, y, pointer, button);
            }

            @Override
            public boolean touchDragged(float x, float y, int pointer) {
                chain_verts.add(x);
                chain_verts.add(Gdx.graphics.getHeight()-y);
                return super.touchDragged(x, y, pointer);
            }
        };

        Gdx.input.setInputProcessor(input_0);
    }

    @Override
    public void render(float delta) {
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        world.step(TIMESTEP, VELOCITYITERATIONS, POSITIONITERATIONS);

        camera.position.set(0, 20, 0);
        camera.update();

        batch.setProjectionMatrix(camera.combined);

        debugRenderer.render(world, camera.combined);
    }

    @Override
    public void resize(int width, int height) {
        camera.viewportWidth = 1200;
        camera.viewportHeight = 800;
    }

    @Override
    public void pause() {}

    @Override
    public void resume() {}

    @Override
    public void hide() {
        dispose();
    }

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

enter image description here

\$\endgroup\$
5
  • \$\begingroup\$ What happens if you don't move the camera in your render method? Does it change the position of the shape? \$\endgroup\$
    – Charanor
    Commented Dec 17, 2017 at 4:10
  • \$\begingroup\$ The shape renders closer to the touch coordinates. \$\endgroup\$
    – BT93
    Commented Dec 17, 2017 at 4:32
  • \$\begingroup\$ The closer I draw the shape to the bottom left corner of the screen the closer the shape is to the original coordinates. The closer to the center of the screen I draw the further away the shape is. \$\endgroup\$
    – BT93
    Commented Dec 17, 2017 at 4:37
  • \$\begingroup\$ Try replacing Gdx.graphics.getHeight() with camera.viewportHeight. If that doesn't work there's one more possible solution I have in store... \$\endgroup\$
    – Charanor
    Commented Dec 17, 2017 at 5:12
  • \$\begingroup\$ Nothing changed :( \$\endgroup\$
    – BT93
    Commented Dec 17, 2017 at 5:45

1 Answer 1

1
\$\begingroup\$

I was only translating the starting coordinate and incorrectly setting the body's position to that coordinate. Instead I now translate each screen coordinate in touchDragged() before adding it to the ArrayList (chain_verts), works now. Also set starting position to (0, 0).

public class Play2 implements Screen {
    private static final float TIMESTEP = 1 / 60f;
    private static final int VELOCITYITERATIONS = 8, POSITIONITERATIONS = 3;

    private Box2DDebugRenderer debugRenderer;
    private OrthographicCamera camera;
    private PolygonSpriteBatch batch;
    private World world;

    private List<Float> chain_verts = new ArrayList<Float>();
    private float[] chain;

    @Override
    public void show() {
        world = new World(new Vector2(0f, -9.81f), true);
        debugRenderer = new Box2DDebugRenderer();
        camera = new OrthographicCamera();
        batch  = new PolygonSpriteBatch();

        InputProcessor input_0 = new GestureDetector(new Gesture() {
        }) {

            @Override
            public boolean touchUp(float x, float y, int pointer, int button) {
                if (chain_verts.size() == 0) {
                    return false;
                } else {
                    chain = new float[chain_verts.size()];
                }

                for (int i = 0; i < chain_verts.size(); i++) {
                     chain[i] = chain_verts.get(i);
                }

                ChainShape chainShape = new ChainShape();
                chainShape.createChain(chain);

                BodyDef bodyDef = new BodyDef();
                bodyDef.type = BodyType.StaticBody;
                bodyDef.position.set(0, 0);

                FixtureDef fixtureDef = new FixtureDef();
                fixtureDef.shape = chainShape;

                world.createBody(bodyDef).createFixture(fixtureDef);

                chain_verts.clear();
                chainShape.dispose();

                return super.touchUp(x, y, pointer, button);
            }

            @Override
            public boolean touchDragged(float x, float y, int pointer) {
                // translate each coordinate here before adding to vertices list
                Vector3 mouse = new Vector3();
                camera.unproject(mouse.set(x, y, 0));

                chain_verts.add(mouse.x);
                chain_verts.add(mouse.y);

                return super.touchDragged(x, y, pointer);
            }
        };

        Gdx.input.setInputProcessor(input_0);
    }

    @Override
    public void render(float delta) {
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        world.step(TIMESTEP, VELOCITYITERATIONS, POSITIONITERATIONS);

        camera.update();
        batch.setProjectionMatrix(camera.combined);
        debugRenderer.render(world, camera.combined);
    }

    @Override
    public void resize(int width, int height) {
        camera.viewportWidth = 1200 / 30;
        camera.viewportHeight = 800 / 30;
    }

    @Override
    public void pause() {}

    @Override
    public void resume() {}

    @Override
    public void hide() {
        dispose();
    }

    @Override
    public void dispose() {
        batch.dispose();
        world.dispose();
        debugRenderer.dispose();
    }
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .