Using retained sprites (ZoomEngine.Graphics) and ZoomEngine.Animation Part 3

When you look at most of the sample code that’s out there for doing 2D XNA games you may notice that there is a tendency to sprinkle in the drawing code all over the place.  Simple samples/tutorials will put it directly in Game.Draw(…) while more complicated projects usually have it inside the game ‘entities’.

In this post, I’d like to present an alternative method that has a number of advantages.  I call this ‘The Retained Sprite Method’.  This isn’t a new concept, and there is nothing magical or complicated about what I’m going to show you, but it will go along way to help clean up your code and make more reusable ‘engine’ components.

What is the retained sprite method?

The idea is that you put all of your drawing code in exactly one place.  I’ll call this the DrawingContext.  Furthermore, your game entities do not typically use the DrawingContext to draw anything…only Sprites do.  A Sprites is a ‘dumb’ (no Update) object that describes what/where to draw.  Your game entities (player, enemy, boss, etc) do all the ‘thinking’ (Update) and create/retain sprites in a sprite tree.  Each frame the entities do not have to do anything to draw the sprites, just being in the tree means the entity is drawn.


Lets look a class diagram:



What you see above is a very simple retained sprite system.  This system supports two types of Sprites. 

FrameSprite will draw a single image to the screen (a Frame describes the Texture, SourceRect, and SpriteEffect to use).

TextSprite will draw a string of text to the screen using a given font & alignment.

You can imagine how such a system could be extended.  In my game engine I have other types of sprites like AvatarSprite, AnimatedSprite, MovieSprite, etc.

You can then build higher level components on top of this.  For example, layout/controls framework uses the sprite tree for it’s rendering.

Some of the advantages of doing your drawing this way are:

  1. You don’t have spriteBatch.Draw code sprinkled all over your codebase.  It’s all in DrawingContext, so you can upgrade/port to new rendering systems easily.
  2. Your game code is more declarative (read ‘clean’), because you’re describing what to draw, instead of how to draw it.
  3. Because it’s more declarative, it naturally lends itself to using an animation system as described in previous posts.
  4. Things like layers, multiple cameras, culling, etc become much easier when you retain a sprite tree.
  5. Sprites can have Children, so doing relative motion is trival.  Whenever a parent sprite moves/rotates, all children are also moved/rotated.  The same applies to Scale/Color.

The sample code below shows how to use this sprite system, and as a bonus I added plenty of animations to show how powerful the combinations of a retained sprite tree with an animation system can be.

If you’re not convinced that this is the way to go, then I invite you to re-create this sample without using the retained sprite tree & post it in the comments.


Comments (4)

  1. josh says:

    Hey. First let me thank you for writing this tutorial. It was very helpful for me.

    I can really see the benefits of using a retained sprite tree. I'm having trouble expanding your example to be able to apply the SpriteEffect.FlipHorizontally effect to a whole tree of sprites. Any tips?  

    My first go was simply applying SpriteEffect.FlipHorizontally to the whole tree, but it's not that simple. For example, if a child sprite is rotated 90 degrees, then applying SpriteEffect.FlipHorizontally to the child makes the child flip vertically relative to the screen, because of its 90 degree angle.

    I can build a matrix for the flip transformation by first translating by the parent's origin and then reflecting over the Y-axis, but I'm not quite sure how to connect that matrix back to my drawing code. Just doing a straight decompose like you've shown is not sufficient.

  2. This is awesome, thank you! 🙂 I'm suspecting it's something like this they're using in Plants Vs. Zombies, right? Do you know if this technique has another name?

  3. Spacebiker says:

    Doing the same retained sprite system for my engine currently.

    As spritebatch cant use matrices for each sprite, do you just use matrices everywhere in sprite tree and decomposeMatrix on demand for drawing?

  4. Crystal Mew says: is the leading provider of WoWGold, FFXI Gil, RS Gold,EverQuest Platinum, and Warhammer online gold.MMOG STOP delivers fast, safe and always guaranteed.

Skip to main content