Comment dessiner du texte lisse dans libgdx?
j'essaie de dessiner du texte simple dans mon jeu android sur libgdx, mais ça a l'air pointu. Comment rendre le texte lisse dans différentes résolutions? Mon Code:
private BitmapFont font;
font = new BitmapFont();
font.scale((ppuX*0.02f));
font.draw(spb, "Score:", width/2-ppuX*2f, height-0.5f*ppuY);
10 réponses
Une solution consiste à utiliser la FreeType extension de libgdx, tel que décrit ici. Cela permet de générer une police bitmap à la volée à partir d'une .police ttf. Généralement, vous le feriez au démarrage Une fois que vous connaissez la résolution cible.
Voici un exemple:
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();
}
font.getRegion().getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);
cela obtient la texture utilisée dans un BitmapFont et change son filtrage à bilinear, permettant une meilleure qualité d'image résultante tout en haut - et en bas de l'échelle au coût de rendu GPU légèrement plus lent (la différence n'est généralement pas perceptible).
vous devriez avoir un coup d'oeil rapide sur les polices de caractères personnalisées et/ou DistanceField-Fonts. Ils sont faciles à comprendre et tout aussi faciles à mettre en œuvre:
https://github.com/libgdx/libgdx/wiki/Distance-field-fonts
DistanceFieldFonts rester lisse, même lorsque vous leur haut de gamme:
- Créer un .fichier fnt utilisant hiero qui est fourni par le site Web de libgdx.
- Réglez la taille de la police à 150; elle créera un .dossier de la TPN et A.fichier png.
- Copiez les deux fichiers dans votre dossier actif.
maintenant, déclarez la police:
BitmapFont font;
maintenant dans la méthode create:
font = new BitmapFont(Gdx.files.internal("data/100.fnt"), false); // 100 is the font name you can give your font any name
rendu:
font.setscale(.2f); font.draw(batch, "whatever you want to write", x,y);
en général, vous ne recevez pas de texte pointu parce que vous concevez votre jeu pour une certaine résolution et quand vous vous déplacez vers un périphérique différent, Libgdx met tout à l'échelle pour correspondre à la nouvelle résolution. Même avec l'échelle de filtrage linéaire est mauvais sur le texte parce que les coins ronds sont facilement déformés. Dans un monde parfait, vous créeriez le contenu dynamiquement à l'exécution en fonction du nombre de pixels disponibles pour vous et pas une seule échelle automatique serait utilisée.
C'est le approche que j'utilise: tout construire pour petit écran (480 x 320), et quand vous l'ouvrez sur une plus grande résolution, je charge le BitmapFont avec une taille plus élevée et applique et inverse l'échelle à celle que Libgdx fera plus tard automatiquement.
voici un exemple pour clarifier les choses:
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);
}
les polices Bitmap sont des textures et si vous voulez que les petites textures paraissent plus lisses lorsque vous les redimensionnez en plus grandes tailles, vous devez vous assurer d'utiliser le bon filtre de texture.
beaucoup de choses obsolète après la mise à jour, c'est ce qui fonctionne pour moi:
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
}
Et quand vous voulez vous rendre sur l'écran:
// text rendering
fontLatoLight.setColor(Color.WHITE); // set color here (has other overloads too)
fontLatoLight.draw(batch, "Hello World!", xCoord, yCoord);
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.
??? Ceci explique juste comment utiliser le .scale() méthode qui je suis en déclarant est obsolète dans la version actuelle.
Ma Solution pour le bon texte avec Libgdx
J'utilise BitmapFont et je génère 3 polices différentes de même taille en utilisant L'outil Hiero exemple Arial 16, Arial 32, Arial 64
je les ai mis dans mon fichier d'actifs et d'utilisation (charge) d'un seul d'entre eux selon la taille de l'écran
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);
}
}
alors j'utilise cette ligne de code pour qualité de résultat supérieure de haut en bas d'Échelle
textGametFont.getRegion().getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);
échelle de l'image
gérer la taille de la police pour tous les types de résolution de l'appareil j'utilise ces deux fonctions
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;
}
la résolution d'écran que j'utilise est
SCREEN_WIDTH = 480
SCREEN_HEIGHT = 320
réglez l'échelle à la police
textGametFont.setScale((xtrans(yourScale)+ ytrans(yourScale))/2f);
et enfin attirer votre texte
textGametFont.draw(batch, "WINNER !!", xTrans(250), yTrans(236));
J'espère que c'était clair et utile !!!
scene2d, si vous voulez appliquer antialiasing à toutes vos étiquettes, mettez ceci sur le constructeur de votre premier écran:
skin.getFont("default-font").getRegion().getTexture().setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
C'est le premier écran de mon jeu:
...
public class MainMenuScreen implements Screen {
public MainMenuScreen() {
...
skin.getFont("default-font").getRegion().getTexture().setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
}
}
le nom de la police est dans interface utilisateur.json fichier, vérifiez que BitmapFont et Label$LabelStyle l'article:
"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",
}
},