Astuces DotNet (Sébastien Courtois)

20/09/2010

[XNA 4] Tutoriel 5 : Création d’un composant XNA : Compteur d’images affichées par secondes

Filed under: Non classé — sebastiencourtois @ 16:53

EDIT 22/09/2010 : Une correction a été faite pour le calcul des FPS.

Nous allons nous intéresser aux composants réutilisables XNA. XNA fournit un Framework d’extensibilité permettant de créer et d’intégrer facilement un composant à une application XNA. Durant cet article, nous allons intégrer un compteur d’images affichées par seconde sur l’application quasiment sans toucher le code original.

Projet de départ

  • Architecture des composants XNA

xna_tuto5_2

L’architecture “composant” de XNA comprend 3 Interfaces :

  1. IGameComponent : Interface de base des composants XNA. Contient une méthode d’initialisation (Initialize)
  2. IUpdateable : Interface pour les composants non graphique. Contient une méthode Update similaire à celle de Game vu dans les tutoriels précédents.
  3. IDrawable : Interface pour les composants graphiques. Contient une méthode Draw similaire à celle de Game.

Deux classes implémentent ces interfaces afin de fournir des composants de base :

  1. GameComponent : Composant de base non graphique implémentant IGameComponent et IUpdateable. Il contient donc une méthode d’initialisation et une méthode de mise à jour.
  2. DrawableGameComponent : Composant de base graphique implémentant GameComponent et IDrawable. Il contient donc une méthode d’initialisation, une méthode de mise à jour et une méthode d’affichage.
  • Création d’un composant graphique : Compteur de FPS (Frames Per Second)

Un composant XNA n’est rien d’autre qu’une classe dérivant de GameComponent ou DrawableGameComponent. Pour commercer, il faut créer un nouvel élément.

xna_tuto5_1

Il existe un templace “GameComponent” pour créer des composants. Vous pouvez l’utiliser ou créer une nouvelle classe vide. Nous appellerons ce composant CompteurFPS. Nous devons ensuite modifier la classe afin qu’elle hérite de DrawableGameComponent. En effet, on souhaite calculer et afficher le nombre d’images par secondes. Le squelette de code pour un composant graphique est le suivant.

public class CompteurFPS : Microsoft.Xna.Framework.DrawableGameComponent
{
    public CompteurFPS(Game game) : base(game)
    {
        // TODO : Code
    }

    public override void Initialize()
    {
        // TODO : Code
        base.Initialize();
    }

    public override void Update(GameTime gameTime)
    {
        // TODO : Code
        base.Update(gameTime);
    }

    public override void Draw(GameTime gameTime)
    {
        // TODO : Code
        base.Draw(gameTime);
    }
}

Pour ce composant, nous avons besoin d’un certain nombre propriétés.

//Composant de dessin
public SpriteBatch spriteBatch;
//Police de caractêres
public SpriteFont spriteFont;
//Nombre d'images par secondes
public double FPS = 0.0f;

La propriété spriteBatch est l’utilitaire qui va nous permettre de dessiner à l’écran (voir Tutoriel 2). La propriété spriteFont est la font que nous allons utiliser pour afficher le texte à l’écran (voir Tutoriel 3).La propriété FPS est une variable pour stocker le nombre d’images par seconde courant.

On va tout d’abord initialiser/charger les deux premières propriétés.

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

protected override void LoadContent()
{
    this.spriteFont = this.Game.Content.Load<SpriteFont>("MyFont");           
    base.LoadContent();
}

On calcule le nombre d’images affichés pour une secondes puis on affiche le résultat sous forme de texte que l’on affichage en haut à droite de l’écran.

public override void Draw(GameTime gameTime)
{
     this.FPS = 1000.0d / gameTime.ElapsedGameTime.TotalMilliseconds; 
    //Formatage de la chaine
    string texte = string.Format("{0:00.00} images / sec", this.FPS);
    //Calcul de la taille de la chaine pour la police de caractère choisie
    Vector2 taille = this.spriteFont.MeasureString(texte);
    //Affichage de la chaine
    this.spriteBatch.Begin();
    this.spriteBatch.DrawString(this.spriteFont, texte, new Vector2(this.GraphicsDevice.Viewport.Width - taille.X, 5), Color.Green);
    this.spriteBatch.End();
    base.Draw(gameTime);
}

Remarque : Le calcul du nombre d’images par secondes aurait pu être fait dans la méthode Draw.Toutefois afin de séparer ce qui est traitement non graphique de ce qui est graphique, j’ai décidé de mettre ce code dans la méthode Update.

Remarque 2 : J’utilise ici la méthode MeasureString de la propriété spritefont qui me permet de calculer la taille du texte que je souhaite afficher  en fonction de la police de caractère sélectionné. Cela me permet de définir où je dois positionner la chaine de caractères pour qu’elle soit visible entièrement dans le coin haut droit de l’écran.

  • Ajout du composant à l’application

Une fois un composant créé, il suffit de l’ajouter à la classe Game au travers de la liste Component.

fps = new CompteurFPS(this);
this.Components.Add(fps);

On se retrouve avec le type d’écran suivant :

xna_tuto5_3

  • Quand les méthodes des composants sont-elles appelées ?

Une fois ajoutés dans la liste des composants, chacun des méthodes d’un cycle XNA (Initialize,LoadContent,Update,Draw…) sont appelées par la classe Game. Game appelle tout d’abord sa propre méthode Initialize puis appelle celle de ses composants.  Chacun des  méthodes Initialize  des composants appellent leurs propres méthodes LoadContent. Une fois ce processus terminé, la classe Game appelle sa propre méthode LoadContent et lance la boucle de jeu.

La boucle de jeu appelle la méthode Update de Game puis celle de ses composants. Il en va de même pour la méthode Draw (celle de Game étant appelée en premier).

Lorsque plusieurs composants sont intégrés, les propriétés DrawOrder et UpdateOrder permettent de définir l’ordre d’appels des méthodes des composants. Le nombre le plus faible est appelé en premier. Si tous les composants sont au même niveau, l’ordre d’ajout dans la liste des composants est l’ordre par défaut (le premier composant ajouté sera appelé en premier).

Les propriétés Enable et Visible permettent d’activer ou désactiver les composants.Ceux-ci sont à true par défaut (activé).

  • Bonus : Mon FPS est bloqué à 60

Par défaut, XNA bride la vitesse d’affichage à 60 images par secondes (30 sur Windows Phone). Cela permet de garantir une bonne fluidité tout en gardant un temps fixe pour tous les calculs annexes (physiques par exemple).

Si vous souhaitez désactiver cette fonctionnalité, il suffit d’ajouter au constructeur de Game les lignes suivantes :

this.IsFixedTimeStep = false;
this.graphics.SynchronizeWithVerticalRetrace = false;
this.graphics.ApplyChanges();

Vous aurez alors le FPS réel de votre application.

xna_tuto5_4

  • Conclusion

Vous savez maintenant créer des composants réutilisables pour XNA 4. De nombreux composants sont disponibles sur Internet et sur le site officiel XNA.

Code Source du tutoriel

Un commentaire »

  1. Eh, pas idiot la procédure pour calculer les FPS. Merci😉

    Commentaire par avant-gardiste — 30/09/2012 @ 20:38


RSS feed for comments on this post. TrackBack URI

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

Créez un site Web ou un blog gratuitement sur WordPress.com.

%d blogueurs aiment cette page :