It is completely a matter of taste.
You could pass your Game
class instance into the constructor of your Sprite
and access its public Services
property. This is what DrawableGameComponent
and GraphicsDeviceManager
do.
You could pass Game.Services
as an IServiceProvider
into the constructor of your Sprite
class. This is what the ContentManager
class does. This has the advantage of not depending on an actual instance of Game
(which you might not have if, say, you end up making a form-based level editor).
You could just pass an instance of SpriteBatch
in the constructor of your Sprite
class, but you can then only create Sprite
objects after you create your SpriteBatch
, which you can only do during and after LoadContent
.
You could get especially lazy and create a globally accessible Game
or IServiceProvider
or SpriteBatch
object and just use that (make it a static property on your game class). Advantage: quick and easy; Disadvantage: ugly!
You could pass a SpriteBatch
instance into your Sprite.Draw
method. This is pretty easy to do, and is the method I use for my gameplay classes - things that might have a Draw
and an Update
function (eg: a Player, or an Enemy, etc). One advantage is that it makes it both locally explicit and easy to modify the shared resources that the Draw
function depends on.
But if your Sprite
class is simply visual data for SpriteBatch
(texture, position, etc), which is managed externally (having public setters for these properties, in your example, indicates that it might be), then I would recommend creating an extension method for SpriteBatch
that does the drawing. This allows you to maintain the "feel" of the SpriteBatch
object. Your extension method might look like:
public static void Draw(this SpriteBatch sb, Sprite sprite)
{
sb.Draw(sprite.Texture, sprite.Position, Color.White);
}
Allowing you to draw it with: sb.Draw(sprite);
. This method is preferable if you are not doing SpriteBatch.Begin
and .End
calls in your Draw
method - as this allows it to work the same as SpriteBatch
.
Those last two methods are the ones that I use and recommend myself.
But you have done something that strikes me as pretty unusual by making your Sprite.Draw
method virtual
- indicating that you will be inheriting from Sprite
and using it virtually. But combining this with public setters, and not calling Begin
and End
, makes for a pretty confused design.
If this is really the design you intend to use, then passing an IServiceProvider
to the Sprite
constructor is probably the best method to use as it allows for better encapsulation. (Just fix up those other things, which don't ;)