XNA – Optimisation de l’affichage d’un score via un composant

Si il y a bien une chose qui est commun à tous les jeux, c’est le fait, à un moment ou un autre, d’afficher un score (ou au moins un nombre).

Voici un exemple de composant simple qui permet d’afficher un score :

public class ScoreDrawer : Microsoft.Xna.Framework.DrawableGameComponent {
        private SpriteBatch spriteBatch;
        private SpriteFont scoreFont;

        private int score;

        public ScoreDrawer(Game game)
            : base(game)
        {
            score = 100;
        }

        protected override void LoadContent()
        {
        // Chargement de la police de caractère 
        this.scoreFont = this.Game.Content.Load<SpriteFont>("scorefont");

        // Récupération du spriteBatch via les services 
        this.spriteBatch = this.Game.Services.GetService<SpriteBatch>();

        base.LoadContent();
        }

        public override void Draw(GameTime gameTime)
        {
            // Affichage du score à l'écran 
            this.spriteBatch.DrawString(this.scoreFont,
                score.ToString(),
                Vector2.Zero,
                Color.White);

            base.Draw(gameTime);
        }
    }

 

Le problème dans ce composant est l’utilisation de la conversion suivante :

score.ToString()

 

Comme la méthode Draw est appelée très régulièrement, cette conversion génère beaucoup de “déchets” en mémoire.

Pour illustrer le déchet, j’ai lancé le profiler mémoire sur une durée de 2 minutes :

memory-profiler

Voici le résultat du profiler au bout de ces 2 minutes  :

1er-scenario

On ne peut pas empêcher le déchet, car il faut bien convertir le score en String pour l’afficher. Mais par contre on peut le limiter en diminuant le nombre de conversions faites. Pour cela, il suffit de stocker le score au format string, et de maintenir à jour cette chaîne en fonction des mises à jours du score.

Comme le code est plus parlant voici :

public class ScoreDrawer : Microsoft.Xna.Framework.DrawableGameComponent {
        private SpriteBatch spriteBatch;
        private SpriteFont scoreFont;

        private int score;
        private string scoreString;

        // Pour simuler la mise à jour du score 
        private int elapsedMS;

        public ScoreDrawer(Game game)
            : base(game)
        {
            score = 100;
            scoreString = score.ToString();
            elapsedMS = 0;
        }

        protected override void LoadContent()
        {
        // Chargement de la police de caractère 
        this.scoreFont = this.Game.Content.Load<SpriteFont>("scorefont");

        // Récupération du spriteBatch via les services 
        this.spriteBatch = this.Game.Services.GetService<SpriteBatch>();

        base.LoadContent();
        }

        public override void Update(GameTime gameTime)
        {
            elapsedMS += gameTime.ElapsedGameTime.Milliseconds;

            // Ici on simule la mise à jour du score toutes les 5 secondes 
            // On pourrait aussi stocker l'ancienne valeur du score et 
            // faire ce calcul lorsque le score change 
            if (elapsedMS >= 5000)
            {
                score += 100;
                // La conversion se fait donc beaucoup moins souvent 
                scoreString = score.ToString();
                elapsedMS = 0;
            }

            base.Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {
            // Affichage du score à l'écran 
            this.spriteBatch.DrawString(
                this.scoreFont,
                scoreString,
                Vector2.Zero,
                Color.White);

            base.Draw(gameTime);
        }
    }

 

En relançant le profiler pendant 2 minutes voici le résultat obtenu :

2ieme-scenario

Il est donc très important de faire attention aux potentiels « déchets ». Surtout ceux produits pendant les méthodes Update et Draw, car elles sont appelées constamment.

One comment on “XNA – Optimisation de l’affichage d’un score via un composant

Répondre à dypeHindRinny Annuler la réponse.

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Vous pouvez utiliser ces balises et attributs HTML : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>