XNA Framework 1.0 Refresh : du texte dans vos jeux

Préambule

Ce petit tutoriel explique simplement comment ajouter grace a la classe SpriteFont du texte dans des applications utilisant le Framework XNA.

Introduction

XNA Framework « Refresh » introduit plusieurs nouvelles classes qui manquaient cruellement dans la première release. Parmi celles-ci se trouve la classe SpriteFont, nous permettant d'afficher du texte d'une façon toute simple et très rapide.

Ce petit tutoriel a pour but d'expliquer comment utiliser cette nouvelle classe.
J'utiliserai le terme anglais « Font » plutôt que « Police de caractères ». Il va de soit que c'est pour une simple raison de fainéantise. Evidemment.

Création de notre Font

Commençons par créer un nouveau projet de type « Windows Game » que nous appellerons « SpriteFontTest ».

Notre projet créé, ajoutons lui notre « SpriteFont ». Pour faire ceci, il suffit de se rendre dans le Menu « Add » de notre projet et de choisir « New Item ».

Oh joie ! Dans les différents choix se trouve justement un nouvel item nommé « SpriteFont » que nous allons sélectionner. Pour ma part, et toujours par pure fainéantise (n'est-ce pas le propre d'un informaticien ?), je laisse le nom par défaut : « SpriteFont1 ».

Cette manoeuvre va ajouter à notre projet un fichier XML avec une extension quelque peu inhabituelle : « .Spritefont ». Dans ce fichier se trouvent plusieurs propriétés de notre Font, telles que sa taille, son style (Regular, Bold, Italic), ainsi que le premier et dernier numéro des caractères de la table ASCII que nous souhaitons générer. Par défaut sont sélectionnés les caractères 32 (espace) jusqu'à 126 (~). Si vous souhaitez par exemple ne générer que les chiffres, vous pouvez modifier ces valeurs par 48 et 57 (tous les chiffres 0 à 9).

Ce fichier XML sera passé à la moulinette via le Content Pipeline à la compilation, qui nous générera un « Bitmap Font » (une représentation de nos caractères sous forme de Sprite). Justement, tant qu'on y est, compilons !
Le compilateur nous retourne une erreur : « The Font family SpriteFont1 could not be found ». En effet, il faut changer le nom de la Font à utiliser (qui est resté par défaut « SpriteFont1 »). Il suffit en fait de modifier le contenu compris entre les balises <FontName></FontName>. Nous allons rester sobre et utiliser la Font nommée « Arial »

<!-- Modify this string to change the font that will be imported -->
<FontName>Arial</FontName>

Par ailleurs, l'aide nous rappelle que certaines Fonts sont parfois soumises à des licences ! Vérifiez donc bien que vous pouvez librement utiliser la font que vous souhaitez avec votre projet.

La compilation se déroule maintenant avec succès. Notons qu'un fichier SpriteFont.xnb a été généré dans le répertoire où se trouve notre exécutable.

Utilisation de notre Font

Nous allons commencer par récupérer notre instance de SpriteFont1. Pour ce faire, nous allons utiliser la même méthode que pour le chargement d'une texture ou d'un Mesh, via le Content Pipeline

this.spriteFont = content.Load<SpriteFont>("SpriteFont1");

Notre instance de SpriteFont expose 2 propriétés et une méthode qui nous intéresserons :

Méthode de la classe SpriteFont
Vector2 MesureString(string text) La méthode MesureString retourne un Vector2 contenant la largeur (propriété X) et la hauteur (propriété Y) du texte que nous lui passons en paramètre.
Propriétés de la classe SpriteFont
LineSpacing Retourne la hauteur entre plusieurs lignes de notre texte
Spacing Permet de récupérer ou de modifier l'espacement entre nos caractères

La classe SpriteBatch se dote quant à elle d'une nouvelle méthode pour nous permettre d'afficher notre texte : DrawString(). Cette méthode attend ces 4 paramètres :

La Méthode SpriteBatch.DrawString()t
SpriteFont spriteFont Notre SpriteFont
String Text Le texte à écrire
Vector2 Position Les coordonnées 2D de notre Texte
Color color La couleur de notre texte

Pour afficher notre texte, il nous faut nous rendre dans la méthode Draw. Voici son contenu final :

private string text = "Hello World From XNA ! Woohoooooooooooo !";
protected override void Draw(GameTime gameTime)
{
    this.graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
    this.spriteBatch.Begin();
    this.spriteBatch.DrawString(this.spriteFont, text, Vector2.Zero, Color.Blue);
    this.spriteBatch.End();
    base.Draw(gameTime);
}

Afin d'utiliser les propriétés et méthodes de la classe SpriteFont, nous allons ajouter ces quelques lignes à la méthode Update :

if(spriteFont.MeasureString(text).X<this.graphics.PreferredBackBufferWidth)
    this.spriteFont.Spacing += 0.05f;

Ces instructions ont pour but d'agrandir l'espacement entre les lettres de notre texte tant que la taille de celui-ci ce dépasse pas la largeur de notre fenêtre.

Recompilons notre solution et lançons l'exécutable généré :

Et voici commence en moins de 10 lignes de code nous avons pu simplement afficher du texte dans notre application XNA !

Code complet

Ci-joint le code complet de cet exemple.

Amusez-vous bien et n'hésitez pas à partager vos créations sur CodeS-SourceS !

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace SpriteFontTest
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        private GraphicsDeviceManager graphics;
        private ContentManager content;
        private SpriteBatch spriteBatch;
        private SpriteFont spriteFont;
        private string text = "Hello World From XNA ! Woohooooooooooooo !";

        public Game1()
        {
            this.graphics = new GraphicsDeviceManager(this);
            this.content = new ContentManager(Services);
        }

        protected override void Initialize()
        {
            base.Initialize();
            this.spriteBatch = new SpriteBatch(this.graphics.GraphicsDevice);
        }

        protected override void LoadGraphicsContent(bool loadAllContent)
        {
            if (loadAllContent)
            {
                this.spriteFont = content.Load<SpriteFont>("SpriteFont1");
            }
        }

        protected override void UnloadGraphicsContent(bool unloadAllContent)
        {
            if (unloadAllContent)
            {
                this.content.Unload();
            }
        }

        protected override void Update(GameTime gameTime)
        {
            if (spriteFont.MeasureString(text).X < this.graphics.PreferredBackBufferWidth)
                this.spriteFont.Spacing += 0.05f;
            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            this.graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
            this.spriteBatch.Begin();
            this.spriteBatch.DrawString(this.spriteFont, text, Vector2.Zero, Color.Blue);
            this.spriteBatch.End();
            base.Draw(gameTime);
        }
    }
}

Références utiles

XNA Game Studio : http://msdn.microsoft.com/fr-fr/library/bb200104(v=XNAGameStudio.40).aspx
Table ASCII : http://www.table-ascii.com/
XNA Framework : Les bases de l'affichage 2D

A voir également
Ce document intitulé « XNA Framework 1.0 Refresh : du texte dans vos jeux » issu de CodeS SourceS (codes-sources.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.
Rejoignez-nous