如何在libgdx中绘制平滑文本?
我试着在我的android游戏中在libgdx上绘制简单的文本,但它看起来很清晰。如何使文本在不同分辨率下看起来平滑?我的代码:如何在libgdx中绘制平滑文本?,libgdx,Libgdx,我试着在我的android游戏中在libgdx上绘制简单的文本,但它看起来很清晰。如何使文本在不同分辨率下看起来平滑?我的代码: private BitmapFont font; font = new BitmapFont(); font.scale((ppuX*0.02f)); font.draw(spb, "Score:", width/2-ppuX*2f, height-0.5f*ppuY); 位图字体是纹理,如果要在将较小的纹理调整为较大尺寸时使其看起来更平滑,则需要确保使用正确
private BitmapFont font;
font = new BitmapFont();
font.scale((ppuX*0.02f));
font.draw(spb, "Score:", width/2-ppuX*2f, height-0.5f*ppuY);
位图字体是纹理,如果要在将较小的纹理调整为较大尺寸时使其看起来更平滑,则需要确保使用正确的纹理过滤器
一种解决方案是使用libgdx的FreeType扩展,如前所述。这允许您从.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();
}
这将获取位图字体中使用的纹理,并将其过滤更改为双线性,从而在向上和向下缩放图像时获得更高的图像质量,但代价是GPU渲染速度稍慢(差异通常不明显)。- 使用libgdx网站提供的hiero创建一个.fnt文件
- 将字体大小设置为150;它将创建一个.fnt文件和一个.png文件
- 将这两个文件复制到您的资产文件夹中
- 现在声明字体:
BitmapFont font;
- 现在在创建方法中:
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);
一般来说,你不会看到清晰的文字,因为你是按照特定的分辨率设计游戏的,当你移动到不同的设备时,Libgdx会缩放所有内容以匹配新的分辨率。即使使用线性过滤,文本缩放也不好,因为圆角很容易变形。在一个完美的世界中,您将根据可用像素数在运行时动态创建内容,而不会使用单一的自动缩放 这就是我正在使用的方法:为小屏幕(480 x 320)构建所有内容,当您以更大的分辨率打开它时,我将以更大的大小加载位图字体,并将其应用到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);
}
公共静态浮标;
公共静态最终int虚拟_宽度=320;
公共静态最终int虚拟_高度=480;
公共void loadFont(){
//与定义的视口相比,真实设备屏幕要大多少
Screen.SCALE=1.0f*Gdx.graphics.getWidth()/Screen.VIRTUAL\u WIDTH;
//防止分辨率小于320x480的设备出现不必要的缩小
如果(Screen.SCALE在更新后有很多东西被弃用,这就是我的工作:
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);
??这只是解释了如何使用当前版本中不推荐使用的.scale()方法。我使用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);
}
}
缩放图像
要处理设备所有类型分辨率的字体大小,我使用这两个函数
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;
}
我使用的模型屏幕分辨率是
屏幕宽度=480
屏幕高度=320
将比例设置为字体
textGametFont.setScale((xtrans(yourScale)+ ytrans(yourScale))/2f);
最后画出你的文字
textGametFont.draw(batch, "WINNER !!", xTrans(250), yTrans(236));
希望这是清楚和有用的!!!在场景2D中,如果您想对所有标签应用抗锯齿,请在第一个屏幕的构造器上显示:
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部分:
查看博客文章。不要缩放,但要为每种字体创建合适的字体。ppu也不好。每一个使用像素转换的教程都会出错。以你决定的对象大小绘制,并告诉相机你的游戏世界要绘制多少。请添加一些解释。他已经对字体纹理应用了线性纹理过滤。似乎我s在某些设备上很有意义——在我的例子中是Nexus7(1代)这个解决方案对我很有帮助。如何使字体纹理生成mipmap?现在,字母是黑色块。这不是绝对正确的。你可以在着色器中为字体着色。你可能想说你一次只能使用一种颜色。但即使这样,也可以通过更复杂的着色器或附加纹理来克服。如何n我是用皮肤做的吗?@AlexKapustian,你有什么解决办法吗……事实上,问题是如何在Scene2d.ui中已有的小部件中使用这个距离域字体功能。这不是最直接的解决办法,因为它需要花一些精力来研究指南,但它是值得的!文本显示得很漂亮!谢谢!这是一个很好的解决方案这种方法使字体明显优于线性筛选。而且似乎比实现距离字段容易得多。请注意,在调整字体大小时,它看起来仍然有点糟糕。如果您有更好的字体大小筛选(或其他)配置,请发表评论generateFont(int)
现在已被弃用。我们应该使用什么方法来生成字体?@user824294只需编辑答案,只需被作者或某个版主接受即可,但您可以看到,这需要付出一些努力来完成所有工作,但所有工作都值得一试。谢谢您。请注意,“hiero”必须从源代码执行,没有可用的预构建jar。Hiero说明如下:
textGametFont.draw(batch, "WINNER !!", xTrans(250), yTrans(236));
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);
}
}
"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",
}
},