3. The TextObject Class
So we have a simple way of representing a sprite, but
it would be very useful to have a corresponding mechanism for
representing text. We achieve this by creating the TextObject
class. Because text shares many of the same features as sprites (a
position, origin, color, rotation, scaling, and more) we derive TextObject from SpriteObject as shown in Figure 2, allowing us to take advantage of all the SpriteObject properties.
The constructors available to this class are more text-oriented and are shown in Listing 6.
Example 6. The available constructors for the TextObject class
public TextObject(Game game)
public TextObject(Game game, Vector2 position)
public TextObject(Game game, Vector2 position, SpriteFont font)
public TextObject(Game game, Vector2 position, SpriteFont font, String text)
public TextObject(Game game, Vector2 position, SpriteFont font, String text,
TextAlignment horizontalAlignment, TextAlignment verticalAlignment)
|
All the SpriteObject properties are relevant to TextObject except for SpriteTexture (we need a font instead of a texture) and SourceRect (which has no relevance to rendering text). We will ignore these, and instead add a couple of new properties of our own:
Font stores a reference to a SpriteFont object that will be used to render the text.
Text stores a text string to be displayed.
HorizontalAlignment and VerticalAlignment offer the creator of the object a simple way of automatically aligning the text around its position.
All four of these properties are backed by a private class variable rather than being autoimplemented using the { get; set; } syntax. This allows us to hook into their set code and perform some additional processing relating to text alignment, an example of which is shown in Listing 7.
Example 7. The implementation of the Text property
public String Text
{
get { return _text; }
set
{
// Has the text changed from whatever we already have stored?
if (_text != value)
{
// Yes, so store the new text and recalculate the origin if needed
_text = value;
CalculateAlignmentOrigin();
}
}
}
|
In each of the properties, if the code detects that a changed value has been provided, it calls into a function named CalculateAlignmentOrigin. This function examines the content of the HorizontalAlignment and VerticalAlignment properties, and if either is set to a value other than Manual, it automatically calculates a new Origin coordinate by calling the SpriteFont.MeasureString
function . This allows the object
creator to instruct the text to be left- or right-aligned, or for it to
be centered (and the same options are available for vertical alignment,
too). With the alignment properties set, this alignment will continue to
be automatically applied whenever an update to the object is made.
Alternatively, either or both of the alignment properties can be set to Manual (which is also their default), in which case the Origin coordinate can be set explicitly by the game.
Next we have the Draw method. TextObject overrides it and replaces the SpriteObject implementation completely, rendering text rather than a texture. The implementation is very simple and is shown in Listing 8.
Example 8. The TextObject Draw method
public override void Draw(GameTime gameTime, SpriteBatch spriteBatch)
{
// Do we have a font? And some text? If not then there is nothing to draw...
if (Font != null && Text != null && Text.Length > 0)
{
// Draw the text
spriteBatch.DrawString(Font, Text, Position, SpriteColor, Angle, Origin, Scale,
SpriteEffects.None, LayerDepth);
}
}
|
Finally, the class overrides the BoundingBox
function to return a box calculated from the measured text size instead
of from the texture size (because we don't use a texture in the TextObject class).
Just as with the SpriteObject class, the TextObject
class gives us an easy-to-use mechanism for representing all the
possible properties of a piece of text that is to be displayed within a
game. Game-specific classes can derive from TextObject if they want to perform their own custom processing (they might override the Update
method, for example, to change the content or positioning of the text),
or alternatively it might be directly instantiated if nothing else is
required for display.