Skip to content

Rainbow
Apps

Rainbow
Apps

One mockup to fit every screen in Libgdx

Introduction

When developping Numbersion, I made mockup of every screen on figma. These mockups have been designing in an arbitrary phone screen size. Personnaly, I chosed 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 rectangle with pixel size it will look smaller on phones with high densities:

Low density screenLow density screen
Low density screenLow density screen
High density screenHigh 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?

Android development

As an aside, I think it's relevant to talk quickly about Android native development. When developping natively, we can use an 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.

The conversion of dp units to pixels is:

px = dp * (dpi / 160)

More documentation about dp

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

Presentation of the utils method

First solution

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.

Problems

There is a major problem, with this simple strategy. It's only working when the smarphone 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 :(

Second solution

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 overlapses. For example:

Overlapsed textures

Oh no it's really bad.

Fix the overlapses

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 overlapse. 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
10-17-2020

Rainbow Apps

Get it on Google Play

© Copyright 2021 Rainbow Apps. All rights reserved.

Rainbow Apps

© Copyright 2021 Rainbow Apps.
All rights reserved.

Get Numbersion app

Get it on Google Play

Follow me