2D-Text

Text Renderer

2D-Text is a text renderer written in C++ that works with a 2D game engine. It is a sprite text renderer. It works with the DirectX API of Windows and uses the game engine's graphics class to load the sprite textures to the system memory and render it with the help of a texture manager.

C++
Sprites
DirectX
Windows

Project Overview


2D-Text is a sprite text renderer written as a module to work with a 2D game engine for Windows. It is written to work with the DirectX API. DirectX contains a complete rendering engine that can perform all the computations required to display complex shapes on the computer screen. The shapes are defined by vertex and primitive data. The DirectX graphics pipeline can be diagrammed, as shown below.



Sprite Text


In a sprite text system, individual letters are contained in a larger texture image. The program determines which part of the larger texture image to display when rendering each character. The example font contains 94 characters. Each individual character is 48 pixels wide and 62 pixels high. It is important in a sprite-based font to start with large images. If the font is scaled down to produce smaller characters, the quality of each character will be high. If the font is scaled up to produce larger characters, the curved edges of the characters will not be as smooth.



The Graphics Class of the Game Engine


The Graphics class is a wrapper class. It wraps the DirectX functions inside custom functions for the game and will redefine the DirectX types with the custom types. The custom functions and types will be used in place of the DirectX equivalent everywhere else in the code. This will limit the use of DirectX specific code to the wrapper classes, which will make it easier to upgrade the custom code to use different APIs in the future. To intialize the Text object, a pointer to the Graphics object is passed as a parameter.

Normally textures are loaded with Graphics::loadTexture function. The loadTexture function loads textures into default D3D memory, which is usually video memory. In order to examine a texture at the pixel level, the texture has to be loaded into system memory. A new function is added to the Graphics class for this purpose. It's named Graphics::loadTextureSystemMem. The system memory pool is specified with the parameter D3DPOOL_SYSTEMMEM.


The TextureManager Class of the Game Engine


The loadTexture function, of the Graphics class, loads the texture data into D3DPOOL_DEFAULT memory. This is normally video memory. If the graphics device is used by another application, it may become unavailable or “lost” to the game. If that happens, the texture data should be released and reloaded as part of the process of recovering the lost graphics device. By creating a separate texture manager class, it's possible to include the code for dealing with a lost device. When the texture is needed in the game, a TextureManager object is created to load and manage each texture. The TextureManager->initialize function saves a pointer to the graphics system and loads the specified texture file from disk. The graphics->loadTexture function saves the width, height, and pointer to the texture data.


The Image Class of the Game Engine


All of the code that is needed to draw and manage a sprite will be incorporated into the Image class. The Image’s initialize function receives a pointer to the Graphics object, the width and height of the image in pixels, the number of columns in the texture, and a pointer to TextureManager that contains the texture. The initialize function saves the pointers to graphics and textureManager. The spriteData structure texture, width, and height members are filled in. The number of columns in the texture is saved. The last step in initializing is to configure spriteData.rect. The structure spriteData.rect specifies a rectangle that may be used to select part of a multi-image texture.
The Image::draw function will draw the image to the screen.


The Text Class


The Text class has all the rules that should be kept in mind while making the sprite text image. It also has the methods that initialize and print the sprite text into the game scene. Care must be taken to ensure that the font texture matches the settings in the Text class. The following are some of the constants defined in text.h and how they relate to the font sprite image/ texture:



Initializing the Sprite Text


The loadTextureSystemMem function is used to load the font texture into system memory in the Text::initialize function. The Graphics *g parameter points to the Graphics object and the char *file parameter is the name of the font texture file. The font texture should be locked before accessing the pixel data.


  • bool Text::initialize(Graphics *g, const char *file)
  • {
  • HRESULT result = graphics->loadTextureSystemMem(file);
  • }

Printing the Sprite Text


One print function does all of the actual printing. The function parameters are the string to print and the X,Y screen location. The width variable is set equal to the width of one character in the sprite texture. The scaledWidth variable contains the width of the scaled character, which is the width of the character after printing. The doAlign(str) function sets the X and Y locations so the string will be aligned, as specified by the align setting.


  • void Text::print(const std::string &str, int x, int y)
  • {
  • UCHAR ch = 0, chN = 0;
  • std::string str2;
  • width = textNS::FONT_WIDTH;
  • int scaledWidth = static_cast<int>(textNS::FONT_WIDTH*spriteData.scale);
  • float saveY=0;
  • int tabX=0, tabW=0;
  • spriteData.x = (float)x;
  • spriteData.y = (float)y;
  • doAlign(str);
  • }