如何在libgdx中绘制流畅的文本?

时间:2013-02-03 17:14:36

标签: libgdx

我尝试在 libgdx 的Android游戏中绘制简单的文字,但它看起来很清晰。如何使文本在不同的分辨率下看起来流畅?我的代码:

private BitmapFont font;

font = new BitmapFont();

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

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

10 个答案:

答案 0 :(得分:51)

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

这将获取BitmapFont中使用的纹理并将其过滤更改为双线性,从而允许更高的图像质量,同时以略微更慢(差异通常不明显)GPU渲染的成本进行上下缩小。

答案 1 :(得分:28)

一种解决方案是使用FreeType扩展到libgdx,如here所述。这允许您从.ttf字体动态生成位图字体。通常,一旦知道目标分辨率,就会在启动时执行此操作。

以下是一个例子:

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 :(得分:22)

您应该快速查看自定义字体着色器和/或DistanceField-Fonts。它们易于理解,同样易于实施:

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

DistanceFieldFonts保持平滑,即使你将它们放大:

enter image description here

答案 3 :(得分:12)

  • 使用libgdx网站提供的hiero创建.fnt文件。
  • 将字体大小设置为150;它将创建一个.fnt文件和一个.png文件。
  • 将这两个文件复制到资源文件夹中。
  • 现在声明字体:

    BitmapFont font;
    
  • 现在在create方法中:

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

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

答案 4 :(得分:6)

一般情况下,由于您正在设计某种分辨率的游戏,并且当您移动到其他设备时,Libgdx会缩放所有内容以匹配新分辨率。即使使用线性滤波,缩放在文本上也很糟糕,因为圆角很容易失真。在完美的世界中,您可以根据可用的像素数量在运行时动态创建内容,而不是使用单个自动缩放。

这是我正在使用的方法:为小屏幕(480 x 320)构建所有内容,当你以更大的分辨率打开它时,我加载了更大尺寸的BitmapFont并应用和反向缩放到那个Libgdx稍后会自动执行。

以下是一个让事情更清晰的例子:

    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);
}

答案 5 :(得分:2)

位图字体是纹理,如果要将较小的纹理调整为更大的尺寸,则需要确保使用正确的纹理滤镜。

This blog post deals with such issues

答案 6 :(得分:2)

在更新后弃用了很多东西,这对我有用:

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
}

当你想在屏幕上呈现它时:

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

答案 7 :(得分:2)

我使用Libgdx获得流畅文本的解决方案

我使用BitmapFont并使用Hiero工具生成3种不同大小的相同字体 例如Arial 16,Arial 32,Arial 64

我把它们放在我的资产文件中并根据屏幕大小使用(加载)其中一个

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);
            }
        }

然后我使用这行代码更高的结果质量向下和向上缩放

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

缩放图像

处理设备的所有类型分辨率的字体大小我使用这两个函数

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;
}

我使用的模型屏幕分辨率是

SCREEN_WIDTH = 480

SCREEN_HEIGHT = 320

将比例设置为字体

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

最后绘制你的文字

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

希望这很清楚,乐于助人!!!

答案 8 :(得分:1)

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.

???这只是解释了如何使用我在当前版本中弃用的.scale()方法。

答案 9 :(得分:0)

scene2d 中,如果要对所有标签应用抗锯齿,请将其放在第一个屏幕的构造函数中:

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

这是我游戏中的第一个屏幕:

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

字体名称位于 ui.json 文件中,检查 BitmapFont Label $ LabelStyle 部分:

"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",
    }
  },