Go to main content

October 21, 2020

Once I finished to develop the board game screen of Numbersion, when I deployed it on my own phone, what a disappointment to see that images were blurring.

By simplicity my images were just the exported image of my mockups on figma, made on a 360x640px screen, so it looks great on phone with the same density of pixels than my mockup. I was confronting of the same problem as the sizing of texture to fit every screens, the density of smartphone screen does matter.

The problem of blurriness is really visible when looking rounded corners, numbers on the board and texts on the screen. Numbers were blurring because I chose for these images to put directly the text inside images unlike other part of the screen where the images were exported without texts.

You can really see these problems by clicking on this image:

Pixellated images and font on xxhdpi screen

To fix this problem, I decided to use Libgdx freetype with ttf font and generate a font on multiple size.

Let's see an example of how I do it for one size:

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 int getFontSize(int fontSize) {
        if (isRatioSuperiorToMockup()) {
            return getFontSizeFromWidth(fontSize);
        }
        return getFontSizeFromHeight(fontSize);
    }

    private static int getFontSizeFromWidth(int fontSize) {
        return (int) (fontSize * Gdx.graphics.getWidth() / SCREEN_WIDTH);
    }

    private static int getFontSizeFromHeight(int fontSize) {
        return (int) (fontSize * Gdx.graphics.getHeight() / SCREEN_HEIGHT);
    }
}
public class FontUtils {

    public static String BIG_FONT_NAME = "BigFont.ttf";

    public static FreetypeFontLoader.FreeTypeFontLoaderParameter getBigFontParameter() {
        FreeTypeFontGenerator.FreeTypeFontParameter parameterBig = new FreeTypeFontGenerator.FreeTypeFontParameter();
        // Define the right font size in function of the density of my screen
        parameterBig.size = ScreenUtils.getFontSize(45);
        parameterBig.magFilter = Texture.TextureFilter.Linear;
        parameterBig.minFilter = Texture.TextureFilter.Linear;

        FreetypeFontLoader.FreeTypeFontLoaderParameter bigFontLoaderParameter = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
        bigFontLoaderParameter.fontParameters = parameterBig;
        bigFontLoaderParameter.fontFileName = "font/LinLibertine_R.ttf";

        return bigFontLoaderParameter;
    }

    public static BitmapFont getBigFont(AssetManager assetManager) {
        return assetManager.get(BIG_FONT_NAME);
    }
}
public interface AssetDescriptors {
    AssetDescriptor<BitmapFont> BIG_FONT = new AssetDescriptor<>(FontUtils.BIG_FONT_NAME, BitmapFont.class, FontUtils.getBigFontParameter());
}
public class NumbersionGame extends Game {

    private AssetManager assetManager;

    @Override
    public void create() {
        this.assetManager = new AssetManager();

        FreeTypeFontGenerator.setMaxTextureSize(FreeTypeFontGenerator.NO_MAXIMUM);
        InternalFileHandleResolver resolver = new InternalFileHandleResolver();
        assetManager.setLoader(FreeTypeFontGenerator.class, new FreeTypeFontGeneratorLoader(resolver));
        assetManager.setLoader(BitmapFont.class, ".ttf", new FreetypeFontLoader(resolver));

        assetManager.load(AssetDescriptors.BIG_FONT);
    }
}

I do not pretend that the solution I used is the best, but for my use case it works great without making the apk heavy. I just chose to make images about 10 times bigger.

I also made a loading screen to load every picture in memory, to prevent showing a blank/black screen on which users can ask himself: "What is going on?".

To summarize, the steps are:

  • Load assets and generate the font useful for the loading screen in the create function of the Game
  • Launch the loading screen and load every other textures and generate other fonts
  • Let's get started :)

An image is more efficient than a long text (do not hesitate to click on the image):

Non pixellated images and font on xxhdpi screen

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.