0
\$\begingroup\$

I was able to do the zoom logic and pan logic, but like in google maps, I want to be able to zoom to the map and at the same time pan the map near to it.

Example

starting position:

enter image description here

zoom to kennedy airport:

enter image description here

As you can see the map is not zoomed to the center ( New York label), because the mouse pointer was on the kennedy airport and a pan is added.

How do the same with libgdx ?

code for map zoom:

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.InputMultiplexer;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Dialog;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.utils.ScreenUtils;


public class GameScreen extends BaseScreen {

    private Image map;

    public GameScreen(Launcher launcher) {
        super(launcher);
    }

    @Override
    public void show() {
        batch = new SpriteBatch();
        // create ui
        stage = new Stage();
        skin = new Skin(Gdx.files.internal("defaultSkin/uiskin.json"));
        final Dialog dialog = new Dialog("Welcome", skin, "dialog") {
            public void result(Object obj) {
                System.out.println("Closed dialog!");
            }
        };
        dialog.setPosition(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2, 0);
        dialog.text("Hello World ! Try to move with mouse and zoom with mouse wheel");
        dialog.button("Close", true); // sends "true" as the result
        dialog.pack();
        dialog.setVisible(true);
        // stage.addActor(dialog);
        // init camera
        camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        camera.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        // init map image
        map = new Image(new Texture("map/World-map4.png"));
        map.setSize(1080, 720);
        // init input processor
        InputMultiplexer multi = new InputMultiplexer();
        multi.addProcessor(stage);
        multi.addProcessor(new InputProcessor() {

            @Override
            public boolean touchUp(int screenX, int screenY, int pointer, int button) {
                return false;
            }

            @Override
            public boolean touchDragged(int screenX, int screenY, int pointer) {
                return false;
            }

            @Override
            public boolean touchDown(int screenX, int screenY, int pointer, int button) {
                System.out.println("clicked: " + screenX + "," + screenY);
                return false;
            }

            @Override
            public boolean mouseMoved(int screenX, int screenY) {
                return false;
            }

            @Override
            public boolean keyUp(int keycode) {
                return false;
            }

            @Override
            public boolean keyTyped(char character) {
                return false;
            }

            @Override
            public boolean keyDown(int keycode) {
                System.out.println("Key down: " + keycode);
                int step = 20;
                int dx = 0;
                int dy = 0;
                if (keycode == Keys.LEFT) {
                    dx = -step;
                }
                if (keycode == Keys.RIGHT) {
                    dx = step;
                }
                if (keycode == Keys.UP) {
                    dy = step;
                }
                if (keycode == Keys.DOWN) {
                    dy = -step;
                }
                camera.translate(dx, dy);
                return true;
            }

            @Override
            public boolean scrolled(float amountX, float amountY) {
                // arbitrary max zoomIn and max zoomOut values here
                if (camera.zoom - amountY >= -0.8f && camera.zoom - amountY <= 2) {
                    camera.zoom -= (float) amountY / 10f;
                    System.out.println("zoom  :" + camera.zoom);
                }
                return true;
            }
        });

        Gdx.input.setInputProcessor(multi);
    }

    @Override
    public void render(float delta) {
        ScreenUtils.clear(0, 0.36f, 0.65f, 1);
        camera.update();
        batch.setProjectionMatrix(camera.combined);
        batch.begin();
        map.draw(batch, 1);
        batch.end();
        stage.act(Gdx.graphics.getDeltaTime());
        stage.draw();
    }

    @Override
    public void dispose() {

    }

}

So following Basic's suggestion:

enter image description here

the main idea is to:

  • given the viewport center
  • given the mouse position
  • calculate tx and ty ( screen relative, not world relative )
  • translate the screen of a fraction of tx andty ( for example tx/2 and ty/2 )
  • zoom
\$\endgroup\$
2
  • \$\begingroup\$ Can you show us how you've done "the zoom logic and pan logic"? \$\endgroup\$
    – Basic
    Sep 2, 2022 at 7:31
  • 1
    \$\begingroup\$ Added the code , see above \$\endgroup\$
    – Vokail
    Sep 2, 2022 at 9:07

1 Answer 1

0
\$\begingroup\$

Fundamentally, you need to perform the following steps:

  • Work out where you want to pan the view to (relative position to current center)
  • Pan the camera
  • Zoom in

You already have the code for 2 and 3...

camera.translate(dx, dy);

camera.zoom -= (float) amountY / 10f;

dx and dy are how far to move the camera horizontally/vertically at the current zoom level.

amountY is how much you want to zoom in by.

So all you need is a method that takes the relative coordinates and zoom level, then applies both...

void MoveAndZoom(float dx, float dy, float zoom) {
    camera.translate(dx, dy);
    camera.zoom -= (float) zoom / 10f;
}

And call it from the appropriate input method (eg touchdown gives you screen coordinates of the touch point which you can use to calculate dx and dy)

\$\endgroup\$
1
  • \$\begingroup\$ thanks, I've added an image to clarify my understanding on the topic \$\endgroup\$
    – Vokail
    Sep 2, 2022 at 11:53

You must log in to answer this question.

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