What is an efficient way to draw sprites in my 2D XNA game? To be more concrete, I have split this question up into 4 questions.
I used to declare Game1’s spriteBatch static, and called SpriteBatch.Begin and .Close in every IDrawable.Draw. That didn’t work well. Giving each drawable it’s own SpriteBatch also didn’t work well.
Q1: I assume it’s best to have one SpriteBatch instance, and only call begin/close once. Is this correct?
Currently, my Game1.Draw looks something like this:
spriteBatch.Begin();
base.Draw(gameTime); // draws elements of Game.Components
// ...
spriteBatch.End();
Q2: This way, Begin is called only once. Is this the way to go? How did you guys solve this?
Q3: Also, every component has it’s own IGameComponent.LoadContent method. Am I supposed to load my content there? Or is it better to load content at a parent class, such as Game1.LoadContent?
I realise that I should never load the same content twice, so I have given my drawable components both a static and a non-static Texture2D, and gave them 2 constructors:
static Texture2D defaultTexture;
public Texture2D MyTexture;
public Enemy()
: this(defaultTexture) { }
public Enemy(Texture2D texture)
{
MyTexture = texture;
}
protected override void LoadContent()
{
if (MyTexture == null)
{
if (defaultTexture == null)
{
defaultTexture = Content.Load<Texture2D>("enemy");
}
MyTexture = defaultTexture;
}
}
This way, the default textures of a class are only loaded the first time LoadContent is called on that class. However, when the parameter texture is specified in the constructor, I’ll have to load that texture beforehand.
Q4: I think there should be better ways to do this. I’m thinking of creating a texture dictionary with their asset names as string. What would you suggest?
You don’t have to have it static. Just make a singleton. Inside
DrawmethodI advice you to open and end the
SpriteBatchwithin one method. It will help you avoid conflicts withSpriteBatchthat started drawing, but didn’t finish.Are you adding your elements to the global collection of components? This is a bad idea to add drawable to this collection. You cannot control the order of drawing, the components are global. See this answer.
Implement in your components IUpdatable and IDrawable and call them in your code where you need it. Get rid of the static stuff and use Dependency Injection istead.
You should load assets when you need it and you are responsible for it. You don’y have to load all 30 levels when user just started the game, do you? For example, when your game starts you load all assets that you need for your start screen and main menu. If you load just what you need the player is happy that game starts fast. Then player wants to start the gameplay. Here you can load the assets on a separate thread to keep the app responsive.
Content.Loadis cached already, so you don’t have to do it.