Как нарисовать гладкий текст в 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);
Ответы
Ответ 1
Одно из решений - использовать расширение FreeType для libgdx, как описано здесь. Это позволяет вам генерировать растровый шрифт "на лету" с помощью шрифта .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
font.getRegion().getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);
Это получает текстуру, используемую в BitmapFont, и изменяет ее фильтрацию на билинейную, что позволяет получить более высокое качество изображения, в то время как увеличение и уменьшение его при стоимости немного медленнее (разница обычно не заметна) рендеринг графического процессора.
Ответ 3
Вы должны определенно быстро просмотреть пользовательские шейдеры шрифтов и/или шрифты DistanceField. Их легко понять и легко реализовать:
https://code.google.com/p/libgdx/wiki/DistanceFieldFonts
DistanceFieldFonts остаются гладкими, даже если вы их масштабируете:
![enter image description here]()
Ответ 4
- Создайте файл .fnt, используя hiero, который предоставляется веб-сайтом libgdx.
- Установите размер шрифта на 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);
Ответ 5
В общем, вы не получаете резкого текста, потому что вы разрабатываете свою игру для определенного разрешения, и когда вы переходите на другое устройство, 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);
}
Ответ 6
Растровые шрифты представляют собой текстуры, и если вы хотите, чтобы меньшие текстуры выглядели более гладкими, когда вы изменяете их размер до больших размеров, вам нужно убедиться, что вы используете правильный фильтр текстур.
Этот пост в блоге посвящен таким проблемам
Ответ 7
Со многими устаревшими обновлениями после обновления это работает для меня:
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);
Ответ 8
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
Мое решение для гладкого текста с Libgdx
Я использую BitmapFont, и я генерирую 3 разных размера одинаковых шрифтов с помощью инструмента Hiero
пример Arial 16, Arial 32, Arial 64
Я помещал их в свой файл активов и использовал (load) только один из них, зависящий от размера экрана
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));
Надеюсь, это было понятно и полезно!!!