Strings, Fonts, Vectors

The String data type

All outputmust be converted to a data type called Stringbefore it can be displayed.

Since String is a data type, you can declare and use String variables in your program.

String: any sequence of text characters (a "string" of characters). The name of the type in C# is either String or string (that is, either upper or lower case refers to the same data type).

String variable: any variable that can hold a string value.

String constant: any sequence of characters enclosed in quotation marks.

Concatenation: The "+" symbol is C#'s concatenation operator. To "concatenate" means to "put together" and it is used to put together two "strings". A string in a programming language is a sequence of text characters (a string of characters).

Example

Create a new C# XNA program called StringTest. Add the following declarations:

String firstName, lastName, fullName;

Note that you can declare more than one variable at a time.

Add the following to your Initialize method, but use your own name:

firstName = "Tom";

lastName = "Kleen";

fullName = firstName + lastName; // runs them together!

fullName = firstName + " " + lastName;

Console.WriteLine(firstName);

Console.WriteLine(lastName);

Console.WriteLine(fullName);

Where is Console? It is the Output window. To make the Output window visible, click on the View tab, then on Output.

Run the program. It writes everything 60 times per second!

But this is an XNA program. We don’t want to write to the Output window; we want to write to the game screen.

It is often necessary to display text in a game program, e.g. to display messages while the game is going on, to display the score, etc. To display text on the screen in an XNA program, we must do two things: (1) get the font that we want to use, and (2) draw the text on the screen.

Fonts

A font is a style of text. The original Windows fonts were Times New Roman, Arial, and Courier New. Now you have considerably more choices. A Windows font is a file that holds instructions for drawing every character in the computer's character set. A typical font has four variations: (1) normal, (2) bold, (3) italic, and (4) bold italic.

XNA does not provide any fonts for you to use. But it does let you add fonts to your games. Fonts must be added to your game project before you can use them in your games. Then when you run your program, they must be loaded into the program's memory before they can be used. Two other common things that must also be loaded into the program's memory before they can be used are images and sounds. These things are called game content.

Adding a Font to an XNA Game

Create a new program called TextOutput.

XNA allows us to add fonts to our games. The font then becomes a content item that we can use in our program. To add a font to an XNA program:

  1. Right click the Content item in the Solution Explorer
  2. From the popup menu, click on Add
  3. From the sub-menu, click on New Item…

  1. We are creating something called a SpriteFont. Click on SpriteFont in the Add New Item – Content window.

  1. We need to give it a name. The name can be anything you want. Just follow the rules for creating names in C#. I have changed the name from the default SpriteFont to MyFont. Do not change the file extension. The file extension must remain spriteFont.
  2. Click on the Add button to add the font to your program.

Visual Studio will immediately open up a window with a lot of cryptic text. This is an XML file ("eXtended Markup Language—a type of data file) that describes the font that you are going to use. You will almost certainly want to make some modifications. By default, you always get this font in XNA 4.0:

14-point Segoe UI Mono regular

To modify the font name

To modify the font name, locate the following lines of code in the XML file. Note that the green text is a comment, just as in the C#/XNA editor window.

<!--

Modify this string to change the font that will be imported.

-->

FontNameSegoe UI Mono</FontName

To change the font name, replace Segoe UI Mono with the name of the font that you want to use. You must spell the font name exactly as it appears in Windows applications. If it is a multi-word font name like Times New Roman, you must have exactly one space between the words Times and New and exactly one space between New and Roman. If you have an extra space, you will get an error when you try to compile your program. If you have a space on the end of the font name, you will get an error when you try to compile your program. Font names are not, however, case-sensitive, so you could use the font name times new roman and your program would work correctly. So, to change the font to Times New Roman, you would have to change the last line of the above code to this:

<FontName>Times New Roman</FontName

To modify the font size

To modify the font size, locate the text that looks like the following.

<!--

Size is a float value, measured in points. Modify this value to

change the size of the font.

-->

<Size>14</Size

Note that the comments say that the size is a float value, which means that you can use numbers with decimal fractions, although the only decimal fraction values that Windows appears to recognize are .0 and .5. To increase the size of our font to 20 points, change the last line of the above code to this:

<Size>20</Size

To modify the font style

There are also Spacing and UseKerning values for XNA fonts, but you usually won't need to change those values. The last font attribute that you may want to change is the Style attribute. Locate the following lines of code:

<!--

Style controls the style of the font. Valid entries are "Regular",

"Bold", "Italic", and "Bold, Italic", and are case sensitive.

-->

<Style>Regular</Style

Note that the comments tell you exactly what the valid entries for Style are. Note that they are case-sensitive, and that the Bold, Italic style has both a comma and a space between the words Bold and Italic. To change the font style to bold and italic, change the last line of code shown above to this:

<Style>Bold, Italic</Style

Once you have set the font name, size, and style, you can close the XML window. You probably won't need to edit it again.

XNA Content: Fonts

After adding the font to your XNA program, it will appear below the Content group in the Solution Explorer.

Loading Content

Once the font has been added to our project, we must do two things: (1) declare a SpriteFontvariable to hold the font, and (2) when the program begins to run, load the font into the SpriteFont variable with a command in the LoadContent method.

To declare a SpriteFont variable, add the following code to the declaration area of the program:

SpriteFont myFont;

Note that SpriteFont appears in light blue, meaning that it is a pre-defined data type. The variable name myFont can be anything as long as it follows the syntax rules of C# for creating an identifier. Note also that the name you choose for your font (myFont in this case) does not have to be the same as the file name that you chose when you were adding the content to your program.

After declaring a SpriteFont variable to hold the font data, the next step is to load the font data into the variable. This is done in the LoadContent method. The LoadContent method gets executed once, at the beginning of the program, before the game loop begins, and is used to load all content. We will look at other types of content later. The code looks like this:

myFont = Content.Load<SpriteFont>("MyFont");

The data type, in this case SpriteFont, goes between the angle brackets (>), and the name that you assigned to the SpriteFont when you added it to your Content folder goes between the quotation marks. This name is not case-sensitive. Note that you do not include the file extension (spriteFont) here.

Drawing Text and the SpriteBatch

Now we have a SpriteFont variableand we have loaded it with an actual font, we can use it to draw text on the screen. Text is drawn in the Draw method. Drawing in XNA works best if all of the drawing commands are collected together and carried out at once. This drawing is done using a variable that XNA has already declared for us. The name of the variable is spriteBatch, and its data type is SpriteBatch. XNA has already declared the variablefor us in the declaration area near the top of the program. It looks like this:

SpriteBatch spriteBatch;

Note that the data type is SpriteBatch (capital S) and the variable is spriteBatch (lower-case S). The spriteBatch variable provides methods for batching together commands for drawing things on the screen. The term sprite refers to anything that can be drawn on the display.

The above statement only declares the spriteBatch variable; it does not actually initialize it. That happens in the LoadContent method, and is also done automatically for us by XNA:

spriteBatch = newSpriteBatch(GraphicsDevice);

Note that object variables (like spriteBatch) are always initialized in an assignment statement that uses the word new (a C# keyword) followed by the type of the data. This is followed by zero or more values (arguments) in parentheses. You'll be seeing a lot of this as we move forward.

After the spriteBatch variable is created in LoadContent, it can be used in the Draw method to draw items on the screen. Before any drawing can be done, however, the following method must be executed:

spriteBatch.Begin();

After the Begin method has been executed, drawing can be done. When all drawing is done, an End method must be executed:

spriteBatch.End();

Calling the End method marks the end of the commands, and tells spriteBatch to send the drawing commands to the hardware.

NOTE: You will get an error if you try to draw anything outside of the spriteBatch.Begin() and spriteBatch.End() pair.

So, before we can draw anything, we need to add the following lines to our Draw method:

spriteBatch.Begin();

spriteBatch.End();

Drawing Text

Text is drawn on the screen with the DrawString method. Text data in C# (and most other programming languages) is called string data, because it is made up of a string of characters. To draw text on the screen, the following information is needed:

  1. The font to use.
  2. The text (string) to draw.
  3. The location to draw the text.
  4. The color of the text.

The font must be a SpriteFont variable. The text must be a character string. The location must be a Vector. And the color must be a Color.

Positioning items: Vectors

All items that are drawn on the screen must be given a position on the screen. XNA uses a 2-dimensional display with X and Y coordinates. By default, our programs will use a display that is 800 pixels wide and 480 pixels tall. The X coordinates will be given in pixels and will range from 0 to 799. The Y coordinates will also be given in pixels and will range from 0 to 479.

The location (0, 0) is the upper-left corner of the screen (not the lower-left that you are used to using in algebra). Screen locations in XNA are given as vectors. A vector is simply an ordered pair of X and Y coordinates.

XNA provides a Vector2data type which is used to hold an X and Y pair. The "2" means that it is a 2-dimensional vector, with an X and a Y coordinate (there are also 3-dimensional vectors, but we won't look at them now). The Vector2 data type has a pre-defined constant called Vector2.Zero which is just a name for the vector (0, 0), which is the upper-left corner of the screen.

All text in XNA is positioned on the screen by providing a Vector2 that gives the upper-left corner of the text. The following screen shows where the word "Hello" would appear if we used a vector with an X value of 400 and a Y value of 240.

Note that even though the location (400, 240) is the center of the screen, the text does not appear centered on the screen. This is because that the vector value is the position of the upper-left corner of the text. So the upper-left corner of the text is in the center of the screen. It takes a little bit more effort to center the text. This is something that we will worry about later.

Drawing Text with the DrawString method

We now know enough to draw some text on the screen. The following command will draw the word "Hello" in the upper-left corner of the screen using the myFont font (declared above) in the color white. This command must appear in the Draw method between the spriteBatch.Begin() statement and the spriteBatch.End() statement.

spriteBatch.DrawString(myFont, "Hello", Vector2.Zero, Color.White);

Changing the text

To change the text, just change the word "Hello" to something else. You must keep the quotation marks, though.

Changing the color

To change the color of the text, just delete the word White (and the period to its left), press the period key on the keyboard, and select the desired color from the popup list.

Try it by adding the following to your Draw method:

spriteBatch.Begin();

spriteBatch.DrawString(myFont, "Hello", Vector2.Zero, Color.White);

spriteBatch.End();

Note that because the Draw method gets executed 60 times every second, that your program is continually drawing the word "Hello" on the screen 60 times each second. It happens so fast that it appears that the word never changes, though.

Change the string constant "Hello" to the string variable myName. Your name should be printed in the top left part of the screen.

Changing the position of the text

The DrawString command that we currently have will always draw the text in the upper-left corner of the screen because we are using the constant Vector2.Zero. If we want to be able to change the location of the text, we will have to use a Vector2 variable instead of a constant. To declare a Vector2 variable, add the following to the declaration area at the top of the program:

Vector2 messageVector;

The word Vector2 is in light blue, which means that it is a pre-defined data type. The word messageVector is the variable name and can be anything as long as it follows the C# syntax rules for creating an identifier. And just as a Color variable consists of four parts, aVector2 variable consists of two parts: the X part and the Y part. And just as we can assign values to the individual parts of a Color variable, we can also assign values to the individual parts of a Vector2 variable. We can assign values to the X and the Y in the Initialize method. Add the following in the Initialize method.

messageVector.X = 0;

messageVector.Y = 0;

Then we can replace the DrawString command in the Draw method with this:

spriteBatch.DrawString(myFont, "Hello", messageVector, Color.White);

The program still draws the string in the upper-left corner of the screen, but because we have used a variable for the text location instead of a constant, we can make the text move by changing the value of the messageVector variable.

Change the two assignment statements in the Initialize method to this:

messageVector.X = 400;

messageVector.Y = 240;

Run the program. This will cause the text to be drawn with its upper-left corner in the center of the screen.

Change the statements in the Initialize method back to this:

messageVector.X = 0;

messageVector.Y = 0;

Then add the following statement to the Update method:

messageVector.X++;

Run the program. This will cause the text's X location to be incremented every 1/60th of a second. The text will move one pixel right every 1/60th of a second. After about 13 seconds (800/60 = 13.33), the text will have moved 800 pixels to the right. Since the screen is only 800 pixels wide, the text will disappear off the right edge of the screen. The X component of the messageVector variable will continue to be incremented, but since it refers to locations that are not on the screen, nothing will be displayed.