mort8088 Just another WordPress site


XNA 4.0 – Tutorial 4 – SpriteBatch Extended

Originally Posted 2010 - A class that inherits from SpriteBatch that will add a method of writing out strings of text with Xbox controller buttons embedded into the text.

I originally got this code from George Clingerman and his post titled "It's a Control Thing (XNA 3.0 BETA)". I had to hack it about and now it's a SpriteBach Extender, So check it out.


For this tutorial I'm using the "Windows Game State Management" template, but will work for any game, if you don't have it yet you can get it as a VS2010 template from here. Make a new project from the GSM template, I called mine Glyph_Tutorial.

You're also going to need some nice button graphics you can get them from the App-Hub site here.  Now add the big image "xboxControllerSpriteFont.tga" to the (Content) project in your solution.

Right click the image and select properties. In the property window change the Content Processor from "Texture - XNA Framework" to "Sprite Font Texture - XNA Framework" it's the third one down from the top in the drop down list if you can't find it.

Add a new class to your main project, I called mine SpriteBatchExtended and have it inherit from SpriteBatch, you'll also want to add a using references for Microsoft.Xna.Framework and Microsoft.Xna.Framework.Graphics in your new class.

Then add the constructor this will take a GraphicsDevice parameter and pass it on to the base constructor to set up all the things we don't need to think about.

We're going to need some place to store the button font so add a public SpriteFont object

Add the new method which is the whole point of what we are doing

This is the least number of parameters that SpriteBatch.DrawString will take so you already know why they are all there.

We will need some constants to represent the buttons in the string we pass to GlifString these strings will be mapped out to the correct characters as we work through the string, so near the top of the class add

I've wrapped them in a #region ... #endregion so you can collapse them out of sight.

Now to change those "words" into something the draw string method will understand we'll need to add a converter like this

If the method can't find what you asked for it'll return a blank string that we'll handle in the draw call, speaking of which, we'd better start fleshing out that method stub we added.

We'll want a few variables to keep track of things

and do some calculations so we're not repeating ourselves

What we are going to do is parse the string one character at a time and as we go we'll write out the relavent string so we need a loop

In this loop we'll fetch the next character in the sequence

If we're building a button reference we need to do different things than if we are building a text string so we had better check for that

As it's the shortest we'll do the buttonTxt == True path first.

Then no matter what, the first thing we do in this path is add the letter to the string we are building.

When we're building the button we have all ready found the starting '[' and so we are now looking for the closing ']' if this letter isn't it, then we can move on to the next letter.

But if it is a ']' we need to pass the string we've built into ChangeButtonType and find out if it really is a button or just some text in square brackets either way we're not building a button anymore and can set that switch back to false.

Seeing that we have a confirmed button we need to modify the output coordinates so that the button comes out in line with the rest of the string

Now we are ready to call the base DrawString method to do the actual drawing, passing in our button font, the code for the required button, output coordinates, drawn in opaque white, with no rotation, a string origin of zero, the buttons scale, no SpriteEfects and on depth layer zero(above everthing I think).

After we've drawn the button we have to set the output coordinates ready for the next string, so we need to add the width of what we just drew to the X position and remove the Y offset we added in case the next part of the string is not a button.

As a last thing the string we just output is no longer needed so we can clear the string buffer.

And we have succesfully drawn a button to the screen, but what if we weren't looking for a button or it was just some text in square brakes, what then? For the else part of our first if, we don't want to append the letter into the string buffer straight away so we need to check to see if it's a special charecter like '[' or '\n' so we start out with a switch statement.

As you can see we're checking letter to see if it's '[' or '\n' anything else will be appended to the string buffer

for the '[' case we have to check if we have data in the buffer

And if we have then we need to output that string by calling the base DrawString method with the spriteFont we were given as a parameter, our string buffer, the requested color, no rotation, a string origin of zero, a scale of one, no SpriteEffects and on depth layer zero. Then add the pixle width of the string to the output X coordinate, and clear the string buffer.

whether or not we had a string to output or not we have to set the buttonTxt to true and load the '[' into the string buffer.

and we're done with finding the start of a button. Now for added flexibility what if you wanted to have a line break in the string allowing you to write out two lines in one statment we'll that would be the job of '\n'

Again we need to check if we have a string in the buffer already and if so call the base StringDraw... Blah blah blah same as last time except we don't update the X coordinate because that is done regardless of outputting a string, just clear the buffer.

you see if we are moving down a line we want to reset the X coordinate to the original coordinate that was passed in and increase the Y by the line height of the string font.

and we're done, almost, what if in all the fun we still have data in the buffer when we reach the end of the for loop? it is possible that we didn't call DrawString and empty the buffer on the last letter, not all strings will end with a button or a line break. so after the closing brace of the for loop add another string check with a draw string if there is data.

after all that you should have a GlifString method that looks like this:-

You didn't think I was going to make you type all that out and figger out where you went wrong did you????

Ok now to USE this in our test project.

Open the ScreenManager.cs in the ScreenManager folder of your main project, line numbers might be off but you'll get the idea...

on line 37 change


on line 54 change


on line 118 change


and add

to the line straight after it.

Lastly open GameplayScreen.cs from the Screens folder and go to the draw method and change line 194 from


and the two lines of text out put here from


Hit F5 select Play Game and lo, marvel at the button picture dancing with the text.

Now there are some limitations on this code, like you can't do rotated text, and it will probably have a fit if you have a '\n' new line in between '[' & ']' but this is one of the most useful bit's of code I've come across.

Experiment with it and let me know what you think.

Comments (0) Trackbacks (0)

Sorry, the comment form is closed at this time.

Trackbacks are disabled.