Tirage XNA :utiliser un spritebatch pendant tout le jeu
-
13-12-2019 - |
Question
Je développe un jeu XNA.Il est temps que je fasse attention à l’architecture.Jusqu'à aujourd'hui, j'ai toujours implémenté ma propre méthode de dessin de cette manière :
public void Draw(SpriteBatch sb, GameTime gameTime)
{
sb.Begin();
// ... to draw ...
sb.End();
}
Je creusais le DrawableGameComponent et j'ai vu que la méthode Draw se présentait de cette manière :
public void Draw(GameTime gameTime)
{
// ...
}
Tout d'abord, je sais que SpriteBatch peut collecter de nombreuses Texture2D entre Begin et End, ce qui peut être utile pour les trier, ou dessiner avec les mêmes effets.
Ma question concerne les performances et le coût de réussite du SpriteBatch.Chez DrawableGameComponent, il est possible d'appeler spritebatch d'un objet de jeu si son spritebatch est public.
Qu'est-ce qui est suggéré, que doit faire un programmeur de jeux Xna ?
Merci en conseil.
La solution
L'un des graves inconvénients de DrawableGameComponent
c'est que vous êtes enfermé dans la signature de méthode fournie.Bien qu'il n'y ait rien de "mal" en soi avec DrawableGameComponent
, ne le considérez pas comme le "une véritable architecture".Tu es mieux en pensant à cela comme un exemple de possible architecture.
Si vous devez passer un SpriteBatch
(ou toute autre chose) à la méthode draw d'un "composant de jeu" - la meilleure façon est le passer comme argument.Tout le reste est compliqué.
Évidemment, cela signifie que vous ne pouvez pas utiliser les fonctionnalités fournies par XNA. GameComponent
système, et vous devez faire votre propre alternative.Mais c'est presque trivial :À son niveau le plus élémentaire, il s'agit simplement d'une liste d'un type de base doté des méthodes virtuelles appropriées.
Bien sûr, si vous devez utiliser GameComponent
- soit ton jeu est tellement simple (ex:un prototype) dont vous ne vous souciez pas vraiment de l'architecture - alors vous pouvez l'utiliser en gros n'importe lequel méthode que vous aimez pour obtenir un SpriteBatch
à votre méthode de dessin.Ils ont tous des inconvénients.
La méthode suivante la plus robuste sur le plan architectural consiste probablement à transmettre votre SpriteBatch
instance dans le constructeur de chacun de vos composants.Cela maintient vos composants découplés de votre classe de jeu.
D'un autre côté, si vous jetez l'architecture au vent, je vous suggère de faire de votre MyGame.spriteBatch
champ public static
.C’est le moyen le plus simple de permettre d’y accéder n’importe où.Il est facile à mettre en œuvre et facile à nettoyer plus tard quand/si vous en avez besoin.
Pour répondre à votre question sur les performances :Tout ce qui a à voir avec le passage d'un SpriteBatch
autour aura un effet presque négligeable sur les performances (en fournissant l'ordre des appels à Draw
/Begin
/End
reste le même).Ne vous inquiétez pas.
(Si tu vois SpriteBatch whatever
dans le code, cela représente une référence.Une référence est une valeur 32 bits (dans un programme 32 bits, ce que sont tous les jeux XNA).C'est la même taille qu'un int
ou un float
.C'est très petit et très bon marché à faire circuler/accéder/etc.)
Autres conseils
Si vous avez trébuché sur cette question, vous regardiez probablement une solution agréable et générique.Je vous suggère de regarder cela:
J'ai ressenti la nécessité de corriger cette question car "Le meilleur moyen est de le transmettre comme un argument. Tout ce que c'est compliqué." est tout simplement
Personnellement, je le fais maintenant de cette façon dans ma classe de jeu de jeu:
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
SpriteBatch = new SpriteBatch(GraphicsDevice);
this.Services.AddService(typeof(SpriteBatch), SpriteBatch);
}
Maintenant, puisque vous ajoutez des éventailgamecomponents dans la méthode d'initialisation de votre classe de jeu, vous pourrez appeler
this.Game.Services.GetService(typeof(SpriteBatch))
Je dirais que c'est l'approche la plus propre pour résoudre le problème.
Si la DrawableGameComponent
devrait faire partie de la vie des parents SpriteBatch
, puis transmettez-le simplement via le constructeur et stockez-le dans un membre privé (ou exposez-le en tant que propriété si vous le souhaitez).
Vous pourriez également exposer le SpriteBatch
comme propriété de votre Game
cours si vous le vouliez, comme vous l'avez suggéré, mais à chaque fois que vous faisiez référence this.Game
, vous devrez le convertir en votre spécifique Game
type de classe.
((MyGame)this.Game).SpriteBatch.Draw(...)
Ou vous pouvez simplement avoir le DrawableGameComponent
créer un nouveau SpriteBatch
.Il n'y a rien de mal à cela (pour autant que je l'aie jamais vu).Je suppose que ça dépend du nombre DrawableGameComponent
s vous allez créer et à quelle fréquence.
Parcourez également les résultats pour un Rechercher DrawableGameComponent
- il y a beaucoup de bons conseils là-bas.