Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

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);
            }
        }
    }
}
share|improve this question
    
Don't hardcode constants. –  David Gouveia Feb 3 '12 at 10:10
    
just use the ASCII table? –  Tili Feb 3 '12 at 12:16
1  
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
add comment

2 Answers

up vote 2 down vote accepted

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 ?

share|improve this answer
    
I've inherit the sprite sheet which contains everything that I need in one tiny file :) –  Neil Knight Feb 7 '12 at 14:06
add comment

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 );                
        }
    }
}
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.