# Cleaner implementation of this draw call

Simple static class that will write out a message that is passed in. The SpriteSheet is 256x256 and the A-Z starts at line 240 and the 0-9 starts at 248. Each character is 8x8. I hate the if (ix >= 32) and wondered if there is a tidier way of doing this? I'm pleased it's only one Draw call, but it looks ugly.

public static class Font
{
private static String chars = "" + //
"ABCDEFGHIJKLMNOPQRSTUVWXYZ      " + //
"0123456789.,!?'\"-+=/\\%()<>:;     " + //
"";

public static void Draw(string msg, SpriteSheet sprites, SpriteBatch spriteBatch, int x, int y, Color color)
{
msg = msg.ToUpper();
for (int i = 0; i < msg.Length; i++)
{
int ix = chars.IndexOf(msg[i]);
int w = 0, h = 240;
if (ix >= 0)
{
if (ix >= 32)
{
w = 32;
h = 248;
}
spriteBatch.Draw(sprites.Sheet, new Rectangle(x + i * 8, y, 8, 8), new Rectangle((ix - w) * 8, h, 8, 8), color);
}
}
}
}

• Don't hardcode constants. – David Gouveia Feb 3 '12 at 10:10
• just use the ASCII table? – Tili Feb 3 '12 at 12:16
• his sheet does not follow the ascii table, he needs to index it, though the method used is a bit dirty... that spaces are killing me... – Blau Feb 3 '12 at 13:34

Sometimes math is the answer. if you use division and modulus, you don't have to worry about adding more nested ifs once you have 3 lines, or 4 lines.

Remember that modulus wraps from 0 to a certain maximum, then repeats.

The horizontal position in the spritesheet sprite_x is the index times char_width, wrapped at the line width.

The vertical position in the spritesheet sprite_y is index / (characters per line) * (character height) + (240, the starting position).

Substituting into your original function, we have

msg = msg.ToUpper();
for (int i = 0; i < msg.Length; i++)
{
int ix = chars.IndexOf(msg[i]);
spriteBatch.Draw(sprites.Sheet, new Rectangle(x + i * 8, y, 8, 8), new Rectangle(ix * 8 % 256,ix / 32 * 8 + 240, 8, 8), color);
}


However. I'd move the constants out a set of const int declarations. This lets you change the configuration, and makes the code more understandable for when you come back in 5 weeks and wonder what exactly the numbers in ix / 32 * 8 + 240 are.

Suggested:

const int LINE_W = 256, FIRST_LINE = 248, CHAR_W = 8, CHAR_H = 8;
static String chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ      " + // I lined these up
"0123456789.,!?'\"-+=/\\%()<>:;  " + // because of my OCD
"";

static void Draw(string msg, SpriteSheet sprites, SpriteBatch spriteBatch, int x, int y, Color color) {
msg = msg.ToUpper();
for (int i = 0; i < msg.Length; i++) {
var index = chars.IndexOf(msg[i]);
var sprite_x = index * CHAR_W % LINE_W;
var sprite_y = index * CHAR_W / LINE_W * CHAR_H + FIRST_LINE;
SpriteBatch.Draw(sprites.Sheet, new Rectangle(x + i * 8, y, 8, 8), new Rectangle(sprite_x, sprite_y, CHAR_W, CHAR_H), color);
}
}


Also, is there a reason you'd use this over using a custom SpriteFont and SpriteBatch.DrawString ?

• I've inherit the sprite sheet which contains everything that I need in one tiny file :) – Neil Knight Feb 7 '12 at 14:06

This is a similar way of doing that, but next time your sprite sheets shoud follow the ascii layout to make it easier... :)

public static class Font
{
private static String chars = "0123456789.,!?'\"-+=/\\%()<>:;";

public static void Draw( string msg, SpriteSheet sprites, SpriteBatch spriteBatch, int x, int y, Color color )
{
int ix, h;
msg = msg.ToUpper( );
for ( int i = 0; i < msg.Length; i++ )
{
h = 240;
ix = (msg[i] - 'A');
if ( ix < 0 || ix > 'Z' - 'A' )
{
ix = chars.IndexOf( msg[i] );
h = 248;
}
if ( ix >= 0 )
spriteBatch.Draw( sprites.Sheet, new Rectangle( x + i * 8, y, 8, 8 ), new Rectangle( ix * 8, h, 8, 8 ), color );
}
}
}