Drawing Dialog Backgrounds in XNA

Written by Dean Edis on .

The fact that XNA comes with minimal built-in ability to display attractive-looking UIs can be seen as both an advantage and a disadvantage.

When you're writing an application that needs to put up a dialog though (and you don't want to break XNA's cross-platform support by using WIN32 calls!), it can be annoying!

We're in the process of writing the infrastructure for our next game, and in it we'd like to be able to display a range of attractive UI styles, without too much overhead.

So to help with this I've written code to display a dialog background using only a template image. The class ensures that the dialog can be displayed at any sensible size, without introducing unpleasant 'stretch' artifacts.

 

To start off with, let's see an example of a dialog template, and how it could be made to appear on the screen:

To display this on our XNA screen at any given size, we first need to split the bitmap into a 3x3 grid of 'virtual' regions. (I've also reduced the size of the template, as it doesn't need to be too big.)

The corner areas will be blitted to the screen without any scaling applied to them. The top and left edges will be stretched in one direction only, and the centre-most region will be scaled in both direction as appropriate.

The result is nice-looking dialog background, regardless of the dimensions of the original template image - You only need to define the size of the 'margin' on your original template image such that it incloses each of the corners.

The code is quite straight-forward, and easy to import into your own projects. Just create an instance of BorderBitmap, passing in your dialog texture and the pixel size of a ‘corner’, then call Draw() from your display code.

Finding dialog templates online isn't too tricky. I certainly recommend here:
http://opengameart.org/

 

I hope you find this useful!

/// <summary>
/// For drawing a textured bitmap where the corner sections remain unscaled but the remaining area is stretched to the desired screen size.
/// </summary>
public class BorderBitmap
{
    private readonly Texture2D m_texture;
    private readonly int m_cornerPixels;

    public BorderBitmap(Texture2D texture, int cornerPixels)
    {
        if (texture == null)
            throw new ArgumentNullException("texture");

        m_texture = texture;
        m_cornerPixels = cornerPixels;
    }

    public void Draw(SpriteBatch spriteBatch, int x, int y, int width, int height)
    {
        var sourceArea = new Rectangle(0, 0, m_texture.Width, m_texture.Height);
        var sourceInnerArea = new Rectangle(m_cornerPixels, m_cornerPixels, sourceArea.Width - 2 * m_cornerPixels, sourceArea.Height - 2 * m_cornerPixels);

        spriteBatch.Draw(m_texture, new Rectangle(x + m_cornerPixels, y + m_cornerPixels, width - 2 * m_cornerPixels, height - 2 * m_cornerPixels), sourceInnerArea, Color.White);

        if (m_cornerPixels > 0)
        {
            DrawSides(spriteBatch, x, y, width, height, sourceInnerArea);
            DrawCorners(spriteBatch, x, y, width, height, sourceInnerArea);
        }
    }

    private void DrawCorners(SpriteBatch spriteBatch, int x, int y, int width, int height, Rectangle sourceInnerArea)
    {
        // Top-left
        spriteBatch.Draw(m_texture, new Vector2(x, y), new Rectangle(0, 0, m_cornerPixels, m_cornerPixels), Color.White);

        // Top-right
        spriteBatch.Draw(m_texture, new Vector2(x + width - m_cornerPixels, y), new Rectangle(sourceInnerArea.Right, 0, m_cornerPixels, m_cornerPixels), Color.White);

        // Bottom-right
        spriteBatch.Draw(m_texture, new Vector2(x + width - m_cornerPixels, y + height - m_cornerPixels), new Rectangle(sourceInnerArea.Right, sourceInnerArea.Bottom, m_cornerPixels, m_cornerPixels), Color.White);

        // Bottom-left
        spriteBatch.Draw(m_texture, new Vector2(x, y + height - m_cornerPixels), new Rectangle(0, sourceInnerArea.Bottom, m_cornerPixels, m_cornerPixels), Color.White);
    }

    private void DrawSides(SpriteBatch spriteBatch, int x, int y, int width, int height, Rectangle sourceInnerArea)
    {
        // Top
        spriteBatch.Draw(m_texture, new Rectangle(x + m_cornerPixels, y, width - 2 * m_cornerPixels, m_cornerPixels), new Rectangle(sourceInnerArea.Left, 0, sourceInnerArea.Width, m_cornerPixels), Color.White);

        // Bottom
        spriteBatch.Draw(m_texture, new Rectangle(x + m_cornerPixels, y + height - m_cornerPixels, width - 2 * m_cornerPixels, m_cornerPixels), new Rectangle(sourceInnerArea.Left, sourceInnerArea.Bottom, sourceInnerArea.Width, m_cornerPixels), Color.White);

        // Left
        spriteBatch.Draw(m_texture, new Rectangle(x, y + m_cornerPixels, m_cornerPixels, height - 2 * m_cornerPixels), new Rectangle(0, m_cornerPixels, m_cornerPixels, sourceInnerArea.Height), Color.White);

        // Right
        spriteBatch.Draw(m_texture, new Rectangle(x + width - m_cornerPixels, y + m_cornerPixels, m_cornerPixels, height - 2 * m_cornerPixels), new Rectangle(sourceInnerArea.Right, m_cornerPixels, m_cornerPixels, sourceInnerArea.Height), Color.White);
    }
}

 

Mr Panda Goes To Vegas

Written by Adrian Killens on .

We're taking Mr Panda to Las Vegas this September where he'll be on display at the CGE Expo, which has just been taken over by our good friends at Retrogaming Roundup, so massive thanks to them! It's looking like it's going to be an awesome few days and takes place September 12th to 14th. 

Buy Tickets Here

UK Gaming Past, Present and Future

Written by Adrian Killens on .

 

The Centre for Computing History is going to be hosting a weekend celebrating the past, present and future of UK gaming at the end of May. Paying homage to everything from Jet Set Willy to Grand Theft Auto and everything between. Even Mr Panda will be making an appearance.

The event is kicking off on Friday 23rd May with one of the increasingly popular Retro Video Game Nights, where you'll be able to play some UK classics, followed by two days of talks and interactive exhibitions. So make sure you get yourself down there!

Full Details and tickets can be found here:

Retro Gaming Night (23rd May 2014)

UK Gaming Past, Present & Future (24th & 25th May 2014)

 

Lunar Panda Deluxe Out Now!

Written by Adrian Killens on .

Lunar Panda Deluxe

Today was a rather exciting one here at Gimpy Software! After nearly a year of development and a month or so of submitting, tweaking and re-submitting Lunar Panda Deluxe we're finally on the Xbox Store. In fact if you turn on your Xbox 360 right this minute and browse to the 'Indie' section then you should see Mr Panda's smiling face on the first screen, hopefully he'll stay there for a little while but if you don't see him the a cheeky search should do the trick.

We got the email last night at around 3am to say that the game had finally been approved and then around 8am Dean "Carmack" Edis made the first ever purchase of Lunar Panda Deluxe.

You can try it for free and if you enjoy it then full version can be yours for a mere $1.

The PC version will be coming shortly!