programming4us
programming4us
MULTIMEDIA

DirectX 10 Game Programming : Adding Text & Creating a Font System Using Sprites

2/7/2012 9:14:08 AM

Adding Text

Over the years, game text has been implemented in multiple ways—texture blits to the screen, vector drawing, and even just the use of message boxes. In modern development, most game libraries support the concept of text rendering, removing the burden of having to implement this yourself. DirectX does support a method of text rendering, but it still requires a bit of work on your part for it to be useful. The following sections describe how font systems are commonly put together.

Textured Fonts

When using text in your game, it is best that all the text appears in a consistent manner. Using a single font style will help in this regard. A font is a series of letters and symbols written in a certain style. In both 2D and 3D games, text is commonly drawn using textured fonts.

Textured fonts, or bitmapped fonts, are based on letters pre-drawn into a texture. The letters are arranged in a grid with a single letter occupying each section of the grid. When it comes time to write out words, the words are built dynamically by drawing the textured letters on the screen. This allows a single series of letters to be used to create any word or phrase you require. Because of the simplistic nature in which the font is used, text rendering can be quite fast. Also, because the fonts are pre-drawn on a texture, the look and feel of the text can be changed by altering the applied texture.

Textured fonts do have some downsides though:

  • They don’t scale well. Because they are pieces of a texture, they can only grow or shrink so much before they become ugly and unreadable.

  • The texture must support every possible letter or symbol you may use. If your game contains only a language such as English, this may not be a problem, but translating your game to a language such as Japanese may make your texture too large.

  • Because there are different amounts of spacing preceding and following each letter, textured fonts sometimes appear odd when writing certain words.

Textured fonts allow for the build-up of words as they’re needed and are managed through a font system.

Figure 1 shows how the letters of a font can be laid out in a texture.

Figure 1. A font layout.


A Font System Explained

Occasionally there are instances when it makes sense to hardcode any text in the game into preexisting graphics; a font system is used when the text that you need to draw needs to be drawn dynamically. Imagine that you’re playing an RPG and you need to talk to a resident in the village. In a hardcoded text system, what the character says is pre-generated into a texture and pulled up at the appropriate time. Depending on the amount of text, that could potentially mean hundreds of textures needing to be loaded just for standard conversations. A dynamic font system allows for the building up of these strings by loading in only a single texture containing all the letters in the font. This method saves load times and a huge amount of otherwise wasted memory.

Font systems commonly use sprites to do the actual text drawing. Each letter uses a single sprite and is drawn in a sequence to spell out words or phrases.

Creating a Font System Using Sprites

The input string comes into the system and is broken up into multiple sprites. These sprites are then positioned correctly and passed to Direct3D to be drawn.

The following sections show how to implement a sprite-based font system.

The FontSprite Structure

The first step is the creation of a FontSprite structure. The FontSprite structure is needed to describe the properties of every letter sprite.

A simple font system requires a simple FontSprite structure. The FontSprite structure is very similar to the GameSprite structure used in the last chapter. The most important difference is the inclusion of a new variable called letterIndex. Each letter in the font texture has an index associated with it, with the first letter ‘A’ being 0, ‘B’ is 1, and so on.

The FontSprite structure is shown here:

// FontSprite structure
typedef struct
{
// sprite details
float width;
float height;

// sprite position
float posX;
float posY;

int letterIndex;

BOOL visible;
}FontSprite;

Translating a String to Sprites

A new function called UpdateText needs to be created to translate the input string into FontSprite structures. For each letter in the string, a FontSprite structure needs to be filled in. Since the string coming through is dynamic, the UpdateText function needs to be able to pick up on the text it contains and generate valid FontSprites. Because of the number of sprites being created, the font system will use sprites from a sprite pool.

The following code sample shows the UpdateText function.

// The string that will be output in sprites
char *message = "HELLO WORLD";
/*******************************************************************
* UpdateText
* Updates the sprites being used for text rendering
* Inputs - void
* Outputs - void
*******************************************************************/
void UpdateText()
{
int curLetterCount = 0;

// loop through the letters in the message string
for (unsigned int i = 0; i < strlen(message); i++)
{
// set the position of the letter
sprites[curLetterCount].posX = (curLetterCount * letterWidth);
// save off the letter index
sprites[curLetterCount].letterIndex = (message[i] - 'A');
// go to the next letter
curLetterCount++;
}
numberOfLetters = curLetterCount;
}


The UpdateText function loops through the input string looking at each letter. The function then determines the letter’s index by subtracting the ASCII value from ‘A’. This index is then stored in the letterIndex variable for passage to the function that updates the sprites in the sprite pool. The posX variable is also set based on the current letter in the string. Because this is a simplified example, only capital letters are supported in the input string.

The function sets a variable called numberOfLetters, which is used during the Render function to tell Direct3D how many sprites are to be drawn in the batch.

Updating the Sprite Pool

After the FontSprite structures are filled out, the system will convert these over to sprite objects within the sprite pool. If you remember from the last chapter, a sprite pool is a collection of general D3DX10_SPRITE structures that can be dynamically repurposed each frame.

Since the sprites in the sprite pool can be used for any letter in the input string, the texture coordinate needs to be constantly changed to reflect the current letter. The texture coordinate for each letter is calculated with the help of the letterIndex variable set during the UpdateText function. The letterIndex is used to reference the letter’s position in the font texture.

spritePool[curPoolIndex].TexCoord.x = (float)((sprites[i].letterIndex *
letterWidth) / fontTextureWidth);

The only change to the Render function is the use of the numberOfLetters variable set within the UpdateText function. This keeps extra sprites in the sprite pool from being drawn when they’re not in use. Figure 2 shows the output of the simple font system.

Figure 2. A font system’s Hello World.


This system is set up to draw a single string and is not meant as a reusable general purpose component. The font system also doesn’t support alpha blending, causing the letters to appear within rectangles.

Other  
 
 
Video tutorials
- How To Install Windows 8

- How To Install Windows Server 2012

- How To Install Windows Server 2012 On VirtualBox

- How To Disable Windows 8 Metro UI

- How To Install Windows Store Apps From Windows 8 Classic Desktop

- How To Disable Windows Update in Windows 8

- How To Disable Windows 8 Metro UI

- How To Add Widgets To Windows 8 Lock Screen

- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010
programming4us programming4us
programming4us
 
 
programming4us