Generating and rendering bitmap fonts

While you may be most familiar with TrueType Fonts (TTF), they are not the best supported approach when it comes to font rendering in games; this also applies to the Libgdx environment. Rendering text from a TTF is a costly process because it involves rasterizing the vector representation of the font onto a texture.

Instead, TTF files are baked into textures or bitmap fonts using an offline tool, such as Hiero, as you will see later in this recipe. This way, the graphics system only needs to load a texture and the location of each contained character. Rendering text becomes a lot simpler: rendering multiple regions using additional logic for correct character positioning. Don't worry, Libgdx does all of this for us!

In this recipe, we will create bitmap fonts from TTF files using Hiero, a tool distributed with the Libgdx package. Then, we will use the result to render text in various ways within a Libgdx application.

Note

Libgdx features a FreeType extension that allows the user to generate bitmap fonts on the fly from TTF files, but it is not compatible with the HTML backend.

Getting ready

To get a hold of Hiero, get the latest Libgdx package and unzip it somewhere in your hard drive (http://libgdx.badlogicgames.com/releases).

For our recipe, we will use the data/fonts/play.fnt file to render text on the screen. We will also be using the samples projects, as usual.

How to do it…

We are going to subdivide the process for this recipe in two steps. First, we will generate our font texture with Hiero, and then, we will cover the rendering process with Libgdx.

Using Hiero to generate bitmap font files

Perform the following steps to run Hiero and generate a bitmap font texture:

  1. Open a command-line window and access the unpacked Libgdx download folder.
  2. Windows users have to enter the following command:
    java -cp gdx.jar;gdx-natives.jar;gdx-backend-lwjgl.jar;gdx-backend-lwjgl-natives.jar;extensionsgdx-toolsgdx-tools.jar com.badlogic.gdx.tools.hiero.Hiero
    

    If you use either Linux or Mac, you need to replace backslashes with forward slashes:

    java -cp gdx.jar:gdx-natives.jar:gdx-backend-lwjgl.jar:gdx-backend-lwjgl-natives.jar:extensions/gdx-tools/gdx-tools.jar com.badlogic.gdx.tools.hiero.Hiero
    

    The following screenshot shows the Hiero bitmap font tool:

    Using Hiero to generate bitmap font files
  3. Take a look at the Font panel and select the font you want to work with. You can either choose from the ones in your System option or pick a TTF file with the File option.
  4. Now, select Size in pixels and whether the resulting font should have the Bold or Italic style.
  5. The Sample Text box shows the characters that the bitmap will contain. Add the characters you require, keeping in mind that this will not suffice for languages that could potentially have thousands of characters, such as Chinese or Korean. The texture will be too big and unsupported by most GPUs.
  6. The Rendering panel contains a preview of the final result. You can change the color with the Color selector in the Effects panel, but it is advisable that you keep it white and change it dynamically from the code, just as we do with regions.
  7. If you want to stop and carry on later, you can always click on File and Save Hiero settings file.... This will let you save the current project, which can be opened by clicking on File and then on Open Hiero settings file....
  8. Once you are done, click on File and Save BMFont files (text)... to generate the texture and a text file that indicates the location of each character within this texture.

Fantastic! You can now generate bitmap fonts.

Rendering bitmap font files with Libgdx

The code for this example is inside the BitmapFontSample class. First, we add our classic Viewport, OrthographicCamera, and SpriteBatch classes. This time, we will also need BitmapFont, the class that handles the loading and rendering of texture-based fonts.

The font is loaded inside the create() method, simply by passing in the data/fonts/play.fnt file:

font = new BitmapFont(Gdx.files.internal("data/fonts/play.fnt"));

By default, a bitmap font will allocate and own its texture, so you need to dispose of it appropriately. We do so in the dispose() method:

font.dispose();

The meaty part takes place inside the render() method, between the calls to begin() and end(). The most straightforward way to render text is through the draw() function in BitmapFont. It takes SpriteBatch, the string you want to render, and a pair of (x, y) coordinates:

font.draw(batch, "This is a one line string", 20.0f, VIRTUAL_HEIGHT - 50.0f);

You can also draw several lines in one go using the drawMultiline() method. It takes the same parameters as draw(), but it looks for line break characters, :

font.drawMultiLine(batch, "This is a
multiline string", 20.0f, VIRTUAL_HEIGHT - 150.0f);

Sometimes, you will have limited space to render your text and you do not want to insert line breaks manually because that could be a pain. It is possible to wrap your text so that it fits within a given width, through the drawWrapped() method:

font.drawWrapped(batch, "[...]", 20.0f, VIRTUAL_HEIGHT - 400.0f, 900.0f);

Note

Please note that the drawWrapped() method is CPU-intensive; consider rendering it to a FrameBuffer object to cache the result.

While working with Hiero, we intentionally made our texture white so that we could change the rendered color programmatically. This can be achieved with the setColor() function, but beware as it is a state-changing procedure, meaning that all subsequent draw calls will have this color applied:

font.setColor(Color.RED);

You can also change the color of a string within a single draw call using special markup:

  • [color-name]: This sets the current color by name from a predefined list
  • [#RRGGBBAA]: This sets the color by a hexadecimal value; AA defaults to 0xFF
  • []: This sets the current color to the previous one
  • [[: This escapes the [ character

To enable this feature, you need to call the setMarkupEnabled(true) method on the font reference. Here are a couple of examples of how to render a multicolor string:

font.draw(batch, "[PURPLE]This [BLUE]is [GREEN]a [YELLOW]cool [ORANGE]multicolor [RED]string", 0.0f, 0.0f);
font.draw(batch, "[#ff00ff]This [#0000ff]is [#00ff00]a [#66ff00]cool [#ffff00]multicolor [#ff0000]string", 0.0f, 0.0f);

The BitmapFont instances can also be scaled using the setScale() method; keep in mind that this is also a state-changing operation:

font.setScale(1.5f);

The following screenshot illustrates the results of this sample. Now, you can add awesome text to your game!

Rendering bitmap font files with Libgdx

How it works…

Even though it makes life so much easier for us, BitmapFont actually works in quite a simple way. It loads a font.fnt file, which is nothing more than a plain text file pointing to a texture. The file contains information of where the characters are located inside the texture and additional font metrics. This data is used to render characters together in a way that makes sense and feels pleasant.

Here is an extract of data/arial-15.fnt:

info face=Arial,Normal size=15 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=0 aa=1 padding=0,0,0,0 spacing=1,1
common lineHeight=17 base=14 scaleW=1024 scaleH=1024 pages=1 packed=0
page id=0 file=arial-15_00.png
chars count=190
char id=33 x=957 y=12 width=1 height=11 xoffset=2 yoffset=3 xadvance=5 page=0 chnl=0

Fonts have a set of metrics associated with them; let's take a look at the basics:

  • Baseline: This is the line to which the characters are bottom-aligned.
  • Ascent: This is the distance between the normal height (the cap height) and the top of the tallest glyph.
  • Descent: This is the distance between the baseline and the bottom of the lowest glyph.
  • Font height: This is the total height of the font; it is used to calculate the distance to the next line. It is also known as line height.

The following diagram illustrates the main features of a font:

How it works…

Libgdx lets you query metrics from a font using the following methods:

font.getAscent();
font.getDescent();
font.getCapHeight();
font.getLineHeight();
font.getSpaceWidth();

You can actually check how much space a piece of text will take on the screen with the given string, using the getBounds() and TextBounds objects it takes. A TextBounds object only has two fields: width and height:

void getBounds(CharSequence str, TextBounds bounds);

There's more…

Although Hiero will serve you well, you might want to take a look at a few alternatives:

You might want to consider packing the font texture with your other sprites in order to reduce the number of texture switches when rendering the scene.

See also

Congratulations! You now know how to create bitmap fonts and render them with Libgdx. It is time to explore some of the fancy effects discussed in the following recipes:

  • The Baking effects into fonts using Hiero recipe
  • The Dynamic font effects using distance fields recipe
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.142.166.31