Printing Text

0
188

Creating the Font Demo Project

A font in XNA is nothing more than a text file—at least, from the programmer’s point of view. When the project is compiled, XNA uses the text file to create a bitmap font on a memory texture and use that for printing text on the screen.

This is a time-consuming process, which is why the font is created at program startup rather than while it’s running. Let’s create a new project and add a font to it.

Creating a New XNA Project

Follow these steps to create a new XNA project in Visual C# 2010:

  1. Start up Visual Studio 2010 Express for Windows Phone (or whichever edition of Visual Studio 2010 you are using).
  2. Bring up the New Project dialog, shown in Figure 3.1, from either the Start Page or the File menu.

    Creating the Font Demo project.
    FIGURE 3.1 Creating the Font Demo project.
  3. Choose Windows Phone Game (4.0) from the list of project templates.
  4. Type in a name for the new project (the example is called Font Demo).
  5. Choose the location for the project by clicking the Browse button, or by typing the folder name directly.
  6. Click OK to create the new project.

The new project is generated by Visual Studio and should look similar to the project shown in Figure 3.2.

The newly generated Font Demo project.
FIGURE 3.2 The newly generated Font Demo project.

Adding a New Font to the Content Project

At this point, you can go ahead and run the project by pressing F5, but all you will see in the Windows Phone emulator is a blue screen. That is because we haven’t written any code yet to draw anything. Before we can print text on the screen, we have to create a font, which is added to the Content project.

In XNA 4.0, most game assets are added to the Content project within the Solution, where they are compiled or converted into a format that XNA uses. We might use the general term “project” when referring to a Windows Phone game developed with XNA, but there might be more than one project in the Solution. The “main project” will be the one containing source code for a game. Some assets, however, might be located just within the source code project, depending on how the code accesses those assets. Think of the Content project as a container for “managed” assets.

A Visual Studio “Solution” is the overall wrapper or container for a game project, and should not be confused with “projects” that it contains, including the Content project containing game assets (bitmap files, audio files, 3D mesh files, and so on).

In this example, both the Solution and the main project are called “Font Demo,” because Visual Studio uses the same name for both when a new Solution is generated. Now, let’s add a new font to the Content project. Remember that the Content project is where all game assets are located.

  1. Select the Content project in Solution Explorer to highlight it, as shown in Figure 3.3.

    Highlighting the Content project.
    FIGURE 3.3 Highlighting the Content project.
  2. Open the Project menu and choose Add New Item. Optionally, you can right-click the Content project in Solution Explorer (Font DemoContent (Content)) to bring up the context menu, and choose Add, New Item.
  3. The Add New Item dialog, shown in Figure 3.4, appears. Choose Sprite Font from the list. Leave the name as is (SpriteFont1.spritefont).

    Adding a new Sprite Font.
    FIGURE 3.4 Adding a new Sprite Font.

A new .spritefont file has been added to the Content project, as shown in Figure 3.5. Visual Studio opens the new file right away so that you can make any changes you want to the font details. The default font name is Segoe UI Mono, which is a monospaced font. This means each character of the font has the same width (takes up the same amount of horizontal space). Some fonts are proportional, which means each character has a different width (in which case, “W” and “I” are spaced quite differently, for instance).

A new Sprite Font has been added to the Content project.
FIGURE 3.5 A new Sprite Font has been added to the Content project.

The SpriteFont1.spritefont file is just a text file, like a .CS source code file, but it is formatted in the XML (Extensible Markup Language) format. You can experiment with the font options in the .spritefont descriptor file, but usually the only fields you will need to change are FontName and Size. Here is what the font file looks like with all comments removed:

[code]
<?xml version=”1.0” encoding=”utf-8”?>
<XnaContent xmlns:Graphics =
“Microsoft.Xna.Framework.Content.Pipeline.Graphics”>
<Asset Type=”Graphics:FontDescription”>
<FontName>Segoe UI Mono</FontName>
<Size>14</Size>
<Spacing>0</Spacing>
<UseKerning>true</UseKerning>
<Style>Regular</Style>
<CharacterRegions>
<CharacterRegion>
<Start>&#32;</Start>
<End>&#126;</End>
</CharacterRegion>
</CharacterRegions>
</Asset>
</XnaContent>
[/code]

Visual Studio Solution (.sln) and project (.csproj) files also contain XML-formatted information!

Table 3.1 shows the royalty-free fonts included with XNA 4.0. Note that some fonts come with italic and bold versions even though the SpriteFont description also allows for these modifiers.

XNA Fonts

Learning to Use the SpriteFont Class

We can create as many fonts as we want in an XNA project and use them at any time to print text with different styles. For each font you want to use in a project, create a new .spritefont file. The name of the file is used to load the font, as you’ll see next. Even if you want to use the same font style with a different point size, you must create a separate .spritefont file (although we will learn how to scale a font as a rendering option).

Loading the SpriteFont Asset

To use a SpriteFont asset, first add a variable at the top of the program. Let’s go over the steps:

  1. Add a new variable called SpriteFont1. You can give this variable a different name if you want. It is given the same name as the asset here only for illustration, to associate one thing with another.
    [code]
    public class Game1 : Microsoft.Xna.Framework.Game
    {
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;
    //create new font variable
    SpriteFont SpriteFont1;
    [/code]
  2. Create (instantiate) a new object using the SpriteFont1 variable, and simultaneously load the font with the Content.Load() method. Note the class name in brackets, <SpriteFont>. If you aren’t familiar with template programming, this can look a bit strange. This type of coding makes the code cleaner, because the Content.Load() method has the same call no matter what type of object you tell it to load.
    [code]
    protected override void LoadContent()
    {
    // Create a new SpriteBatch, which can be used to draw textures.
    spriteBatch = new SpriteBatch(GraphicsDevice);
    // TODO: use this.Content to load your game content here
    SpriteFont1 = Content.Load<SpriteFont>(“SpriteFont1”);
    }
    [/code]

If the Content class did not use a templated Load() method, we would need to call a different method for every type of game asset, such as Content.LoadSpriteFont(), Content.LoadTexture2D(), or Content.LoadSoundEffect().

There is another important reason for using a template form of Load() here: We can create our own custom content loader to load our own asset files! XNA is very extendable with this capability. Suppose you want to load a data file saved by your own custom level editor tool. Instead of manually converting the level file into text or XML, which XNA can already read, you could instead just write your own custom content loader, and then load it with code such as this: Content.Load<Level>(“level1”)

The ability to write code like this is powerful, and reflects a concept similar to “late binding.” This means the C# compiler might not know exactly what type of object a particular line of code is referring to at compile time, but the issue is sorted out later while the program is running. That’s not exactly what’s happening here, but it is a similar concept, and the easiest illustration of template programming I can think of.

These are just possibilities. Let’s get back to the SpriteFont code at hand!

Printing Text

Now that we have loaded the .spritefont asset file, and XNA has created a bitmap font in memory after running the code in LoadContent(), the font is available for use. We can use the SpriteFont1 object to print text on the screen using SpriteBatch.DrawString(). Just be sure to always have a matching pair of SpriteBatch.Begin() and SpriteBatch.End() statements around any drawing code.

Here are the steps you may follow to print some text onto the screen using the new font we have created:

  1. Scroll down to the Draw() method in the code listing.
  2. Add the code shown in bold.
    [code]
    protected override void Draw(GameTime gameTime)
    {
    GraphicsDevice.Clear(Color.CornflowerBlue);
    // TODO: Add your drawing code here
    string text = “This is the Segoe UI Mono font”;
    Vector2 position = new Vector2(20, 20);
    spriteBatch.Begin();
    spriteBatch.DrawString(SpriteFont1, text, position, Color.White);
    spriteBatch.End();
    base.Draw(gameTime);
    }
    [/code]

Run the program by pressing F5. The WP7 emulator comes up, as shown in Figure 3.6.

Printing text in the Font Demo program.
FIGURE 3.6 Printing text in the Font Demo program.

The version of SpriteBatch.DrawString() used here is the simplest version of the method, but other overloaded versions of the method are available. An overloaded method is a method such as DrawString() that has two or more different sets of parameters to make it more useful to the programmer. There are actually six versions of DrawString(). Here is an example using the sixth and most complex version. When run, the changes to the text output are dramatic, as shown in Figure 3.7!

[code]
float rotation = MathHelper.ToRadians(15.0f);
Vector2 origin = Vector2.Zero;
Vector2 scale = new Vector2(1.3f, 5.0f);
spriteBatch.DrawString(SpriteFont1, text, position, Color.White,
rotation, origin, scale, SpriteEffects.None, 0.0f);
[/code]

Experimenting with different DrawString() options.
FIGURE 3.7 Experimenting with different DrawString() options.

As you have learned in this hour, the font support in XNA takes a little time to set up, but after a font has been added, some very useful and versatile text printing capabilities are available. We can print text via the SpriteFont.DrawString() method, with many options available such as font scaling and different colors.