Go to main content

When developing Numbersion, I made mockup of every screen on figma. These mockups have been designing in an arbitrary phone screen size. Personally, I chose a 360x640px (a 16/9 screen).

The size of pixels depend on the number of pixel and the size of the screen. If we draw a rectangle with pixel size it will look smaller on phones with high densities:

Low density screenLow density screen
High density screenHigh density screen

Unfortunately, not all phones has the same screen size. And the ratio is not always 16/9. For example, tablets are more often on 4/3 or 16/10. So, how can you, with a single mockup, fits every screen with libgdx?

As an aside, I think it's relevant to talk quickly about Android native development. When developing natively, we can use another unit which is density independant: the density-independant pixel (dp).

Unlike pixel for which the size depends on the screen number of pixel, 1dp will look the same on any screens. The baseline density is 160 dpi: aka 1dp = 1px.

Unfortunately, I did not find any principle like this in libgdx. So I had to make my own dynamic size.

In theory the principle is quite simple, just a simple cross-multiplication.

public class ScreenUtils {

    private static final int SCREEN_WIDTH = 360;
    private static final int SCREEN_HEIGHT = 640;

    public static final float getWidth(float assetWidth) {
        return assetWidth * Gdx.graphics.getWidth() / SCREEN_WIDTH;
    }

    public static final float getHeight(float assetHeight) {
        return assetHeight * Gdx.graphics.getHeight() / SCREEN_HEIGHT;
    }
}

Then I use these twos methods when I want to resize my Textures/Actors.

There is a major problem, with this simple strategy. It's only working when the smartphone of the user has a screen with a 16/9 ratio. Otherwise, the textures will be misshapen.

Board with misshapen cases

As you can it's not so great :(

To have a well display of my board and cases, I decided to size my board only with the getWidth method.

And tada, I get a nice board:

Board with right cases proportion

You are maybe thinking it's the end, but unfortunately it is not.

With the previous strategy you can have texture which overlaps. For example:

Overlapsed textures

Oh no it's really bad.

The idea will be to calculate the ratio of the current screen and compare it to the mockup ratio.

If the ratio is superior to the mockup one it's fine, the texture will not overlap. There will be only just more vertical spaces.

Otherwise, let's use the getHeight method. This will fit well, but the drawback is that we will get some blanks on the left and right of the content.

public class ScreenUtils {

    private static final int SCREEN_WIDTH = 360;
    private static final int SCREEN_HEIGHT = 640;

    private static boolean isRatioSuperiorToMockup() {
        float currentRatio = Gdx.graphics.getHeight() / Gdx.graphics.getWidth();

        return currentRatio > SCREEN_HEIGHT / SCREEN_WIDTH;
    }

    public static final float getWidth(float assetWidth) {
        if (isRatioSuperiorToMockup()) {
            return assetWidth * Gdx.graphics.getWidth() / SCREEN_WIDTH;
        }

        return getHeight(assetWidth);
    }

    public static final float getHeight(float assetHeight) {
        return assetHeight * Gdx.graphics.getHeight() / SCREEN_HEIGHT;
    }
}

And here we are:

Final display when ratio inferior to 16/9

You can find me on Twitter if you want to comment this post or just contact me. Feel free to buy me a coffee if you like the content and encourage me.