SyntaxHighlighter

Saturday 5 February 2011

Sphero progress update

The first of many updates on Sphero. My plan is to blog all the way through the development of the game to try and keep myself on track. Anyone who's gone back and read the previous entries in this blog will see that keeping on track is something that I struggle with!

So without further ado, here is the first progress update on Sphero.

So far I've implemented creating 2D terrain inside my map editor in the form of ledges or solid paths. You simply click where you would like the next node to go. The nodes can also be dragged and moved around to alter the shape of the ledge.

I've also implemented this ledges into Alta, having the engine create EdgeShapes using Farseer to create solid terrain.

Finally, I've created the first prototype of the basic movement mechanics for the main character. They're very rough at the moment, but as I'm going for a rapid prototyping approach, they're good enough at this point.

Finally, I whipped up a quick map and put together a demo:

http://www.youtube.com/watch?v=69jQG3r5I88

That's all for now. I'm hoping to get some more of the movement mechanics done today, so I may have another video for you soon!

Thursday 3 February 2011

2D Rendering with SpriteBatch: My approach

I'll be posting an update (along with hopefully a video of the first prototype) of my progress on Sphero at the weekend, but today I wanted to take a second to share my approach to 2D rendering using SpriteBatch.
SpriteBatch itself if an optimisation feature of XNA, grouping and/or sorting sprites to reduce the number of draw calls or textures swaps that need to take place to render the scene. However, the performance benefit from using a SpriteBatch can vary depending on how its used.

The approach I took was to try and figure out what the optimal way of using sprite batch was, and then try and work the rest of my engine around that. The following is the approach I came up with.

***HEALTH WARNING***

This method has not been tested on an Xbox, so I can give no guarentees about it's performance.

At the centre of the set-up are a class, a struct, and 2 dictionarys.

The key to it all is the RenderManager class. However, I won't say too much about this class just yet.

I'm going to try and go through these in a logical order. First of all, we have a dictionary which contains all of the textures we use in the game, with their names as keys (you could use unique ID number if you prefer, I

just find strings easier to work with and remember). All textures are loaded through the RenderManager class, which loads the texture from the content pipeline, and stores it in the Texture dictionary with its name as its key.

The next piece of the puzzle is the RenderObject2D struct. A better name might have been the 'sprite' class, as this is essentially what it is. It holds all of the information needed for the RenderManager to draw the sprite that it describes. This includes a string representing the texture of the sprite.

The penultimate item that makes up this system is the Layer Dictionary.

This is not quite as it sounds. This is not a Dictionary, but rather a Dictionary. The int refers to the order of the layers, the string is used by the game code to tell the RenderManager which layer to add the new sprite to.

Finally we get to the RenderManager.

The RenderManager does 3 main jobs. It loads and stores textures (as we've already seen). It keeps track of all of the sprites to be drawn this frame, and it does the actual drawing.

Essentially the way all of this fits together is this:

Each frame, the game code calls RenderManager.AddToScene() in place of its normal draw calls. This (heavily overloaded) method takes all of the parameters you would need in a SpriteBatch.Draw() call, with two big differences. The first is that instead of a reference to a texture, it passes the name of the texture, and the second is that instead of a depth parameter, it passes the name of a layer.

Inside the RenderManager, every time AddToScene() is called, a RenderObject2D struct is created and filled out with all of the parameters barring the layer name.

Next, the RenderObject2D Struct is stored inside what is effectivey a 3 dimensional array (List>> scene). This is indexed by layer and texture.

In plain english, the scene is a List of layers. Each layer is a list of sub-layers grouped by texture. Each sub-layer is a list of RenderObject2Ds.

After all other components have had 'draw' called on them, RenderManager's draw() method is called. The RenderManager then starts a spriteBatch in 'immediate' mode, and then loops through the scene, starting with the backmost layer, looping through each Texture sub-layer to ensure the minimum number of texture swaps.

Essentially this means the sprites never need sorting, because they were filed away in the right place when they were added to the RenderManager's scene.

There are some optimisations around the Lists to ensure that they dont alloate memory each frame from resizing, and it could be made more efficient by drastically reducing the size of a RenderObject2D by using a numeric identifier for textures, but that should give you a flavour of how I've approached dealing with SpriteBatch.

Now the question is, have I got this completely wrong? Is there a glaringly obvious reason not to go down this route? What are the pros and cons?

I'd love to hear your thoughts!