In a previous Post it was pointed out that using game components can lead to multiple sprite batches in each component. A solution to this was presented to me by Neil Gannon and I am applying it here to multiple components were each component just has a sprite batch draw event and each component
public class Game1 : Microsoft.Xna.Framework.Game
{
MovingCircle myCircle;
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
.
.
Then in the game initialize function we create the sprite batch as a service and we set up the moving service components. The Constructor for the Moving Circle Component accesses the Game Components and adds itself. Hence the commented out line below. Again Neil’s style.
protected override void Initialize()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
this.Services.AddService(typeof(SpriteBatch), spriteBatch);
for (int i = 0; i < 9; i++)
{
myCircle = new MovingCircle(this);
//this.Components.Add(myCircle);
}
base.Initialize();
}
Now to the Game Draw event.
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
base.Draw(gameTime);
spriteBatch.End();
}
Note: The base.Draw(gameTime); call before the End() call allows all the Draw() events of the components to be marshalled before the sprite batch End() call commits the draws to the graphics device.
The Code for the Moving Circle Class is thus….
public class MovingCircle : Microsoft.Xna.Framework.DrawableGameComponent
{
SpriteBatch spriteBatch;
Texture2D movingCircle;
Vector2 movingCirclePosition;
Vector2 Target;
.
.
public MovingCircle(Game game)
: base(game)
{
spriteBatch = (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch));
game.Components.Add(this); // Add yourself
}
// The component adds its own content
protected override void LoadContent()
{
movingCircle = Game.Content.Load<Texture2D>("MovingCircle");
movingCirclePosition = new Vector2(LocalRand.RMinMax(0,600), LocalRand.RMinMax(0,400));
Target = new Vector2(LocalRand.RMinMax(0, 600), LocalRand.RMinMax(0, 400));
}
// Update the moving Circle
public override void Update(GameTime gameTime)
{
movingCirclePosition = Vector2.Lerp(movingCirclePosition, Target, 0.1f);
if (Vector2.Distance(movingCirclePosition, Target) < 0.2)
{
Random r = new Random();
movingCirclePosition = Target;
Target = new Vector2(r.Next(600), r.Next(400));
}
base.Update(gameTime);
}
// Line up the Draw() for this component
public override void Draw(GameTime gameTime)
{
spriteBatch.Draw(movingCircle, movingCirclePosition, Color.Red);
base.Draw(gameTime);
}
The Result

The Code is here