web-dev-qa-db-fra.com

Comment dessiner du texte fluide dans libgdx?

J'essaie de dessiner du texte simple dans mon Android sur libgdx, mais il est net. 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);
33
JustOneMan

Une solution consiste à utiliser l'extension FreeType de libgdx, comme décrit ici . Cela vous permet de générer une police bitmap à la volée à partir d'une police .ttf. Généralement, vous le feriez au moment du 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();
}
28
Rod Hyde
font.getRegion().getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);

Cela obtient la texture utilisée dans un BitmapFont et change son filtrage en bilinéaire, permettant une qualité d'image résultante plus élevée tout en la faisant monter et en descendant à l'échelle au prix d'un rendu GPU légèrement plus lent (la différence n'est généralement pas perceptible).

51
bluepuppy

Vous devriez certainement avoir un aperçu rapide des shaders de polices personnalisées et/ou des polices DistanceField. Ils sont faciles à comprendre et à mettre en œuvre de la même manière:

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

Les polices DistanceField restent fluides, même lorsque vous les augmentez:

enter image description here

22
TheWhiteLlama
  • Créez un fichier .fnt en utilisant hiero qui est fourni par le site Web de libgdx.
  • Définissez la taille de la police sur 150; il créera un fichier .fnt et un fichier .png.
  • Copiez les deux fichiers dans votre dossier d'actifs.
  • Déclarez maintenant 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
    
  • En rendu:

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

En général, vous n'obtenez pas de texte net parce que vous concevez votre jeu pour une certaine résolution et lorsque vous passez à un autre appareil, Libgdx met tout à l'échelle pour correspondre à la nouvelle résolution. Même avec un filtrage linéaire, la mise à l'échelle est mauvaise sur le texte car les coins arrondis sont facilement déformés. Dans un monde parfait, vous créeriez le contenu dynamiquement lors de l'exécution en fonction du nombre de pixels disponibles et aucune échelle automatique ne serait utilisée.

Voici l'approche que j'utilise: tout construire pour un petit écran (480 x 320), et lorsque vous l'ouvrez sur une résolution plus grande, je charge le BitmapFont avec une taille plus élevée et applique et une échelle inverse à celle que Libgdx plus tard faire 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);
}
6
sheitan

Les polices bitmap sont des textures et si vous souhaitez rendre les textures plus petites plus lisses lorsque vous les redimensionnez à des tailles plus grandes, vous devez vous assurer que vous utilisez le bon filtre de texture.

Ce billet de blog traite de ces problèmes

2
Glogo

Avec beaucoup de choses obsolètes après la mise à jour, voici 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 le rendre à l'écran:

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

Ma solution pour un texte fluide avec Libgdx

J'utilise BitmapFont et je génère 3 polices de même taille différentes à l'aide de l'outil Hiero, exemple Arial 16, Arial 32, Arial 64

Je les mets dans mon fichier d'actifs et n'utilise (charge) qu'un seul d'entre eux en fonction de 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);
            }
        }

puis j'utilise cette ligne de code pour une qualité de résultat supérieure de mise à l'échelle vers le haut et vers le bas

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

redimensionner l'image

pour gérer la taille de la police pour tout type de résolution d'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 du modèle que j'utilise est

SCREEN_WIDTH = 480

SCREEN_HEIGHT = 320

Réglez l'échelle sur la police

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

et enfin dessiner votre texte

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

J'espère que c'était clair et utile !!!

2
Netero
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.

??? Cela explique simplement comment utiliser la méthode .scale () que je déclare être obsolète dans la version actuelle.

1
shajeer puzhakkal

Dans scene2d, si vous voulez appliquer l'anticrénelage à 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);

Ceci 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 le fichier i.json, vérifiez BitmapFont et 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",
    }
  },
0
Andreybeta