Learning Windows 8 Game Development
上QQ阅读APP看书,第一时间看更新

Text rendering

So now that we have some images rendering to the screen, you're ready to start making millions. But wait, how are you going to communicate with the player? If you are making an art game, you could probably get away with zero text, but most games need to communicate with the players so they have the information they need to play successfully. To do this, we need to render some text.

Windows has plenty of built in text functionality for rendering text in Windows 8 applications; however, we're working with raw Direct3D, so we don't have access to that, and in many cases those nice features would get in the way of our games.

Thankfully we don't need to worry about perfect kerning and other text features that are needed for a great reading experience, so text rendering becomes really easy. Add in the SpriteFont class from DirectXTK and you'll be subtitling everything before you know it.

TTF versus BMP

Many fonts these days are stored as something called a True Type Font (TTF). These define all of the details about the fonts and store them in a vector graphic form (not the same as vectors in the previous section) so that the operating system can render text in a crisp, correct fashion. Reading and correctly rendering these files is a complicated endeavour, and for many games the detail just isn't needed. Therefore we need another solution.

Enter the bitmap font. A bitmap font takes that detailed processing and does it all up front so we get a nice texture with every character we need rendered out. This way, rendering text is as simple as just drawing the part of the texture that contains the glyph you want, and doing this for every letter in the word or sentence.

Building the font

As I just mentioned, we need to process the original TTF font into a texture that we can use for rendering. Thankfully DirectXTK provides a command-line tool that will do this for us quickly and easily. If you're using NuGet, you can find a pre-compiled version of this tool in the following directory:

packages\directxtk<version number>\tools\native

MakeSpriteFont.exe can also be found with the source code for this chapter, as well as in source code form from the DirectXTK repository mentioned at the start of this chapter.

MakeSpriteFont has a number of configuration options that you can use to tailor your font file.

For the example game, we'll generate a simple sprite font for the Segoe UI font that ships with Windows 8. Remember that when you add fonts to your game, you need to ensure you're licensed to distribute them with software.

Start a command prompt at the location of MakeSpriteFont.exe and run the following command:

MakeSpriteFont.exe "Segoe UI" "GameFont.font"
Note

To quickly open the command prompt in your current folder, hold Shift while you right-click and select Open Command Prompt Here.

This will output a file named GameFont.font, which we can include in our game as we did with the images previously. Don't forget to set the Content property to true.

Drawing the font

Now let's get this text onto the screen. The steps here are pretty simple, just like our sprite rendering before.

Inside the game we need to define a SpriteFont that will hold our font data and work with SpriteBatch to render the text. Add this underneath the SpriteBatch definition:

std::shared_ptr<DirectX::SpriteFont> _spriteFont;

Now we need to load this up using the constructor of SpriteFont. The best place to do this would be after loading the sprites inside the Game->Load() function.

Microsoft::WRL::ComPtr<ID3D11Device> d3d11Device;
m_d3dDevice.As(&d3d11Device);
_spriteFont = std::make_shared<DirectX::SpriteFont>(
  d3d11Device.Get(),
  L"GameFont.font"
);

Here we need to get the ID3D11Device version of our graphics device, and we only have the ID3D11Device1 version. So, just as with our earlier conversion of the device context, use the ComPtr type to help convert and give us a device we can use.

After that, we just need to provide that device, as well as a wchar_t path to our font file, relative to the application directory. In our case we are storing our font in the root game directory.

Now we have the font loaded and ready, and it is a simple matter of drawing it within the same batch we use for the sprites.

Just before we end the sprite batch, add the following lines:

auto textPos = DirectX::XMFLOAT2(10, 10);
auto textVec = DirectX::XMLoadFloat2(&textPos);
_spriteFont->DrawString(
_spriteBatch.get(),
  L"Learning Game Development",
  textVec,
  DirectX::Colors::Green
);

Here we need to specify the position of the text, so as before we need to get FXMVECTOR, which defines that point. To create the vector, we always have to start with XFLOAT2 or a similar type, so we'll define that as a local variable for this demonstration.

Once we have that vector, we can call DrawString on the sprite font. This will handle all of the drawing, and provide us with some parameters to customize the text at runtime. SpriteFont uses SpriteBatch to do rendering, so it needs a reference to that, and we need to specify the text to actually draw as a wchar_t string. The last mandatory parameter is the position of the text, represented by our vector from the given line.

The third parameter is one we haven't seen before, and is something that can be quite useful at runtime, even for rendering sprites. This is the TintColor parameter, which defines a tint to be applied to the image being drawn. Our sprite fonts are generated as pure white characters so that you can easily apply a color tint at runtime, or stick to the default white color for text.

This parameter, however, asks for a color in the form of a vector, so the DirectX::Colors namespace gives us access to many pre-defined common colors that you might want to use. In this case we're using green for the text, which you'll be able to see when you run the game.

If you run your game now you should see some text in the top-left corner of the screen, with the tint color you chose (green if you are following along).

Try changing the tint color or moving the text around the screen. There are plenty of things you can do with just some simple text. Change the font and take a look at the other overloads in SpriteFont. Rendering text can be a challenge to get right; it can break the feel of the game if it doesn't fit in. Experiment and find what fits for your visual style.