How to draw smooth text in libgdx?

。_饼干妹妹 提交于 2019-12-17 08:25:04

问题


I try to draw simple text in my android game on libgdx, but it's look sharp. How to make text look smooth in different resolutions? My Code:

private BitmapFont font;

font = new BitmapFont();

font.scale((ppuX*0.02f));

font.draw(spb, "Score:", width/2-ppuX*2f, height-0.5f*ppuY);

回答1:


One solution is to use the FreeType extension to libgdx, as described here. This allows you to generate a bitmap font on the fly from a .ttf font. Typically you would do this at startup time once you know the target resolution.

Here's an example:

int viewportHeight;
BitmapFont titleFont;
BitmapFont textFont;

private void createFonts() {
    FileHandle fontFile = Gdx.files.internal("data/Roboto-Bold.ttf");
    FreeTypeFontGenerator generator = new FreeTypeFontGenerator(fontFile);
    FreeTypeFontParameter parameter = new FreeTypeFontParameter();
    parameter.size = 12;
    textFont = generator.generateFont(parameter);
    parameter.size = 24;
    titleFont = generator.generateFont(parameter);
    generator.dispose();
}



回答2:


font.getRegion().getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);

This gets the texture used in a BitmapFont and changes its filtering to bilinear, allowing higher resulting image quality while both up- and downscaling it at the cost of slightly slower (the difference is usually not noticeable) GPU rendering.




回答3:


You should definitly have a quick look on custom font shaders and/or DistanceField-Fonts. They're easy to understand and similarly easy to implement:

https://github.com/libgdx/libgdx/wiki/Distance-field-fonts

DistanceFieldFonts stay smooth, even when you upscale them:




回答4:


  • Create a .fnt file using hiero which is provided by libgdx website.
  • Set the size of font to 150; it will create a .fnt file and a .png file.
  • Copy both files into your assets folder.
  • Now declare the font:

    BitmapFont font;
    
  • Now in create method:

    font = new BitmapFont(Gdx.files.internal("data/100.fnt"), false); // 100 is the font name you can give your font any name
    
  • In render:

    font.setscale(.2f);
    
    font.draw(batch, "whatever you want to write", x,y);
    



回答5:


In general you don't get sharp text because you are designing your game for a certain resolution and when you move to a different device, Libgdx scales everything to match the new resolution. Even with linear filtering scaling is bad on text because round corners are easily distorted. In a perfect world you would create the content dynamically at runtime according to the number of pixels available to you and not a single automatic scale would be used.

This is the approach I'm using: Building everything for small screen (480 x 320), and when you open it on a bigger resolution, I load the BitmapFont with a higher size and apply and inverse scale to the one that Libgdx will later do automatically.

Here's an example to make things clearer:

    public static float SCALE;
    public static final int VIRTUAL_WIDTH = 320;
    public static final int VIRTUAL_HEIGHT = 480;


    public void loadFont(){

     // how much bigger is the real device screen, compared to the defined viewport
     Screen.SCALE = 1.0f * Gdx.graphics.getWidth() / Screen.VIRTUAL_WIDTH ;

     // prevents unwanted downscale on devices with resolution SMALLER than 320x480
     if (Screen.SCALE<1)
        Screen.SCALE = 1;

     FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal("data/Roboto-Regular.ttf"));

     // 12 is the size i want to give for the font on all devices
     // bigger font textures = better results
     labelFont = generator.generateFont((int) (12 * SCALE));

     // aplly the inverse scale of what Libgdx will do at runtime
     labelFont.setScale((float) (1.0 / SCALE));
     // the resulting font scale is: 1.0 / SCALE * SCALE = 1

     //Apply Linear filtering; best choice to keep everything looking sharp
     labelFont.getRegion().getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);
}



回答6:


Bitmap fonts are textures and if you want to make smaller textures look smoother when you are resizing them to bigger sizes you need to make sure you use the right texture filter.

This blog post deals with such issues




回答7:


With many things deprecated after the update, this is what's working for me:

public void regenerateFonts(OrthographicCamera cam, Game game) {
    int size = 18;

    if (cam != null && game != null) {
        // camera and game are provided, recalculate sizes
        float ratioX = cam.viewportWidth / game.getW();
        float ratioY = cam.viewportHeight / game.getH();
        System.out.println("Ratio: [" + ratioX + ":" + ratioY + "]");

        size *= ratioY;
    }

    // font parameters for this size
    FreeTypeFontParameter params = new FreeTypeFontParameter();
    params.flip = true; // if your cam is flipped
    params.characters = LETTERS; // your String containing all letters you need
    params.size = size;
    params.magFilter = TextureFilter.Linear; // used for resizing quality
    params.minFilter = TextureFilter.Linear; // also

    // Lato Light generator
    FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal("fonts/Lato-Light.ttf"));

    // make the font
    fontLatoLight = generator.generateFont(params);
    generator.dispose(); // dispose to avoid memory leaks
}

And when you want to render it on the screen:

// text rendering
fontLatoLight.setColor(Color.WHITE); // set color here (has other overloads too)
fontLatoLight.draw(batch, "Hello World!", xCoord, yCoord);



回答8:


My Solution for smooth text with Libgdx

I use BitmapFont and I generate 3 different size same fonts using Hiero tool example Arial 16 , Arial 32, Arial 64

I put them in my assets file and use (load) only one of them depeding on the size of screen

if(Gdx.graphics.getWidth() < (480*3)/2)
        {
            textGametFont = BitmapFont(Gdx.files.internal(nameFont+16+".fnt"),
                    Gdx.files.internal(nameFont+16+".png"), false);
        }else
        {
            if(Gdx.graphics.getWidth() < (3*920)/2)
            {

                textGametFont = new BitmapFont(Gdx.files.internal(nameFont+32+".fnt"),
                        Gdx.files.internal(nameFont+32+".png"), false);
            }else
            {
                textGametFont = new BitmapFont(Gdx.files.internal(nameFont+64+".fnt"),
                        Gdx.files.internal(nameFont+64+".png"), false);
            }
        }

then I use this line of code to higher result quality of down and up Scaling

textGametFont.getRegion().getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);

scale the image

to handle the size of the font for all type of resolution of device I use those two functions

public static float xTrans(float x)
{
    return x*Gdx.graphics.width/(YourModel.SCREEN_WIDTH);
}

public static float yTrans(float y)
{
    return y*Gdx.graphics.height/YourModel.SCREEN_Height;
}

the model screen resolution that i use is

SCREEN_WIDTH = 480

SCREEN_HEIGHT = 320

Set the scale to the font

textGametFont.setScale((xtrans(yourScale)+ ytrans(yourScale))/2f);

and finally draw your text

textGametFont.draw(batch, "WINNER !!", xTrans(250), yTrans(236));

Hope this was clear and helpful !!!




回答9:


private BitmapFont font;

font = new BitmapFont();

font.scale((ppuX*0.02f));

font.draw(spb, "Score:", width/2-ppuX*2f, height-0.5f*ppuY);

    Check out [this](http://www.badlogicgames.com/wordpress/?p=2300) blog post.

??? This just explains how to use the .scale() method which I'm stating is deprecated in the current release.




回答10:


In scene2d, if you want apply antialiasing to all your labels, put this on constructor of your first screen:

skin.getFont("default-font").getRegion().getTexture().setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);

This is the first screen in my game:

...
public class MainMenuScreen implements Screen {    
    public MainMenuScreen() {
        ...
        skin.getFont("default-font").getRegion().getTexture().setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
    }
}

Font name is in ui.json file, check for BitmapFont and Label$LabelStyle section:

"com.badlogic.gdx.graphics.g2d.BitmapFont": {
    "default-font": {
      "file": "default.fnt"
    }
  },
"com.badlogic.gdx.scenes.scene2d.ui.Label$LabelStyle": {
    "default": {
      "font": "default-font",
      "fontColor": "white",
    }
  },


来源:https://stackoverflow.com/questions/14675007/how-to-draw-smooth-text-in-libgdx

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!