Chapter 4. HUD and Text Display

In this chapter, we will learn about text output. We will look deeper into how fonts are created and stored and analyze the possible problems of AndEngine's way of displaying text characters. We will also learn how to create multilingual games and how to localize them.

We will see how to put text on a screen utilizing a heads-up display (HUD) in order to display the score of the game. Alternative ways of displaying text messages will also be discussed.

Finally, we will cover the basics of Android and AndEngine logging and debugging output.

Fonts and text

A font is a file that defines the characters and sometimes special glyphs and symbols that can be printed on the screen. Fonts are typically defined as vectors. Because AndEngine and the OpenGL library in general don't work with vectors, we must first create a raster or bitmap font. We can imagine it as printing the entire alphabet with special characters using a font of our choice on an image and cutting out the letters. Afterwards, we create words using these cut-outs.

The following code shows how we load the font in the ResourceManager class:

//font
public Font font;

public void loadFont() {
  font = FontFactory.createStroke(activity.getFontManager(), activity.getTextureManager(), 256, 256, Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD), 50, true, Color.WHITE_ABGR_PACKED_INT, 2, Color.BLACK_ABGR_PACKED_INT);
  font.load();
}

The first parameter passed is the FontManager class. It's an AndEngine class that takes care of managing the fonts. The second parameter is the TextureManager class. We pass it in because, as we will see later in this chapter, the font is basically a texture onto which we print letters.

The third and fourth parameters are the font texture width and height. The texture used is a minimal texture that can hold the entire English alphabet using the given font and size. We are going to see how the size of the texture can lead to common problems with fonts in AndEngine.

The fifth parameter is the font used. In this example, we are using a built-in font that is available on every Android device. However, it can actually differ in size a little on different Android versions. The sixth parameter, 50, is the size of the font.

The next parameter tells AndEngine to use anti-aliasing to smoothen the edges of the text. It is followed by the eighth parameter, the font color. In our case, we will use white.

The last two parameters define a stroke around each letter as a two-pixels-wide black line.

When this code is called, the texture for the font is prepared. The font object is ready to be used for outputting text. However, the font texture is empty at this moment. How is that possible? Simply because AndEngine loads the letters and puts them onto the texture only when they are needed for the first time. This is called lazy loading.

We can force AndEngine to load all letters that we are going to use by calling the font.prepareLetters() method.

Note

AndEngine's lazy loading can cause a small lag each time a new letter is loaded. It's advisable to load the letters in advance at the beginning of the game.

Storing the font on a texture

Because AndEngine works with its own surface view, it can't simply output text as regular Android apps do. It must draw the text using small sprites. Each letter is in fact a sprite on its own. They are assembled into words by the Text class.

Let's see what happens when we load the Latin alphabet. We start with all uppercase letters and some special characters. The following assignment can be added to the loadFont() method in the ResourceManager class:

font.prepareLetters("01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ.,!?".toCharArray());

We are using the toCharArray() method because the prepareLetters() method expects an array of characters.

Tip

You can opt to render only the characters that you are really going to use. Also, you can call the method with a sentence. Any repeating characters will be rendered only once and a space is not rendered at all. For example, in the sentence in the following line of code, only one E will be rendered on the texture:

font.prepareLetters("GAME OVER!".toCharArray());

The final texture will look something like the following screenshot. Note that the texture is 256 pixels wide and 256 pixels tall. Each character is defined as a texture region in this texture.

Storing the font on a texture

A texture 256 x 256 pixels large can fit all numbers, all uppercase Latin alphabet letters, a comma, a period, an exclamation mark, and a question mark.

Tip

If we try to load more characters than the texture can fit, the game will crash. In reality, we would define a bigger texture.

Storing special characters and international alphabets

There are a few prerequisites for using special characters and international alphabets. First, the font used must contain them. The Android system font contains most of the UTF characters. However, some custom fonts don't. Second, AndEngine treats all letters as sprites; boxed entities, written from left to right. Any other writing systems that compile the words in a different way are not supported.

All this is very important to take into account when localizing games to other languages. Let's discuss what happens when using different international alphabets.

Characters from European languages

Most of the European language alphabets contain characters with a diacritic. They are rendered just fine, but they usually take more space. They must be rendered as separate characters and also the characters are usually taller.

First, we preload some of the characters to the texture map as follows:

font.prepareLetters("01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ ÁÉ".toCharArray());

The result is shown in the following screenshot:

Characters from European languages

The letters with diacritic take more space vertically. AndEngine will take care of the right positioning. Both top and bottom diacritics are rendered correctly.

Also notice that the width of each letter is different. The two new letters are the same width as the four punctuation marks combined.

Korean, Chinese, Japanese, and other similar writing systems

Generally, writing systems that contain separate characters can be rendered.

The Korean alphabet, Hangul, is in fact a syllabary. Each character is constructed from vowel and consonant parts. To render Hangul in AndEngine, you have to prepare each combination separately. This can make the texture pretty big, but it still works.

The same is true for the Japanese alphabet. Each character of both hiragana and katakana (Japanese syllabic writing system) must be rendered separately, even the characters with Japanese diacritic dakuten (double dot or circle). This can be changed by overriding the Text class and adding a special rule. But, this override is not implemented in AndEngine itself.

Finally, Chinese characters and Japanese Kanji (adopted Chinese characters) can be rendered easily. But, there are many of them. A larger texture might be needed.

Let's change the code to include the characters we would like to render. This can be done as follows:

font.prepareLetters("한글中文ひらがなカタカナ".toCharArray());

The following screenshot shows these Korean, Chinese, and Japanese characters rendered on to a texture:

Korean, Chinese, Japanese, and other similar writing systems

If you can read Japanese, maybe you have noticed that the katakana part is composed only of ka, ta, and na, and one ka is missing. Each character is rendered only once, therefore the character ka is rendered only once.

Other writing systems

AndEngine has a problem rendering other writing systems. For example, Thai script, Arabic script, or the script used to write the Hindi language can't be rendered correctly. It is possible to implement a custom rendering, but it would take quite a lot of work.

Let's try to prepare some Hindi, Thai, and Arabic alphabet with this code:

Other writing systems

The following screenshot shows the result. Notice that there are some extra characters rendered separately and in general, it doesn't look like the text in the preceding line of code. This is due to the fact that some writing systems work very differently from the Latin alphabet, and AndEngine doesn't support them at all.

Other writing systems

Workaround for unsupported languages

It is always possible to pre-render the text using other graphics software and use it as sprites when needed. This might not be an option in text-heavy games, but the only other option is to create a custom rendering for writing systems that are not supported.

Other limitations of the font texture

Another thing to watch out for is the size of the font. The font is rendered only once in the size specified when creating the font object. If you want to use fonts of different sizes, you can either scale the Text entity or create multiple font objects in different sizes.

..................Content has been hidden....................

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