0
votes

I am learning the use of libgdx and I got confused by the viewport and how objects are arranged on the screen. Let's assume my 2D world is 2x2 units wide and high. Now I create a camera which viewport is 1x1. So I should see 25% of my world. Usually displays are not square shaped. So I would expect libgdx to squish and stretch this square to fit the display.

For a side scroller you would set the viewport height the same as the world height and adjust the viewport width according to the aspect ratio. Independent of the aspect ratio of your display you always see the full height of the world but different expansions on the x-axis. Somebody with a wider than high display could look further on the x-axis than somebody with a square shaped display. But proportions will be maintained and there is no distortion. So far I thought I mastered how the viewport logic works.

I am working with the book "Learning LibGDX Game Development" in which you develop the game "canyon bunny". The source code can be found here:

Canyon Bunny - GitHub

In the WorldRenderer Class you find the initilization of the camera:

private void init() {
        batch = new SpriteBatch();
        camera = new OrthographicCamera(Constants.VIEWPORT_WIDTH, Constants.VIEWPORT_HEIGHT);
        camera.position.set(0, 0, 0);
        camera.update();
    }

The viewport constants are saved in a separate Constants-Class:

    public class Constants {
        // Visible game world is 5 meters wide
        public static final float VIEWPORT_WIDTH = 5.0f;
        // Visible game world is 5 meters tall
        public static final float VIEWPORT_HEIGHT = 5.0f;
    }

As you can see the viewport is 5x5. But the game objects have the right proportion on my phone (16:9) and even on a desktop when you change the windows size the game maintains the correct proportions. I don't understand why. I would expect that the game tries to paint a square shaped cutout of the world onto a rectangle shaped display which would lead to distortion. Why is that not the case? And why don't you need the adaption of width or height of the viewport to the aspect ratio?

2
Apparently a change in VIEWPORT_WIDTH doesn't change the appearance of the game at all. The game looks the same for VIEWPORT_WIDTH = 100 and VIEWPORT_WIDTH = 1. Doesn't make sense to me. VIEWPORT_HEIGHT does change the appearance.Peter

2 Answers

0
votes

The line:

cameraGUI.setToOrtho(true);

Overrides the values you gave when you called:

cameraGUI = new OrthographicCamera(Constants.VIEWPORT_GUI_WIDTH, Constants.VIEWPORT_GUI_HEIGHT);

Here's the LibGDX code that shows why/how the viewport sizes you set were ignored:

/** Sets this camera to an orthographic projection using a viewport fitting the screen resolution, centered at
     * (Gdx.graphics.getWidth()/2, Gdx.graphics.getHeight()/2), with the y-axis pointing up or down.
     * @param yDown whether y should be pointing down */
    public void setToOrtho (boolean yDown) {
        setToOrtho(yDown, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
    }

    /** Sets this camera to an orthographic projection, centered at (viewportWidth/2, viewportHeight/2), with the y-axis pointing up
     * or down.
     * @param yDown whether y should be pointing down.
     * @param viewportWidth
     * @param viewportHeight */
    public void setToOrtho (boolean yDown, float viewportWidth, float viewportHeight) {
        if (yDown) {
            up.set(0, -1, 0);
            direction.set(0, 0, 1);
        } else {
            up.set(0, 1, 0);
            direction.set(0, 0, -1);
        }
        position.set(zoom * viewportWidth / 2.0f, zoom * viewportHeight / 2.0f, 0);
        this.viewportWidth = viewportWidth;
        this.viewportHeight = viewportHeight;
        update();
    }

So you would need to do this instead:

cameraGUI.setToOrtho(true, Constants.VIEWPORT_GUI_WIDTH, Constants.VIEWPORT_GUI_HEIGHT);

Also don't forget to call update() right after wherever you change the position or viewport dimensions of your camera (Or other properties)

0
votes

I found the reason. If you take a look on the worldRenderer class there is a method resize(). In this method the viewport is adapted to the aspect ratio. I am just wondering because until now I thought the resize method is only called when resizing the window. Apparently it's also called at start up. Can anybody clarify?