This blog is no longer updated. Feel free to copy any useful information to other blogs or wikis as this site may not exist for much longer. Thanks.


Scaling retro sprites at build time

February 20th, 2010 | 2 comments

For my new game, I still am sticking with a retro feel of blowing up sprites 4x their original size to give them that blocky look. However, unlike Pixel Man where I did this as a “post process” by rendering the whole game tiny and scaling that up, I want to scale up each sprite individually in order to have smoother motion as things move around. I therefore had a few options:

1) Scale each sprite individually when drawing. Pros: easy initially. Cons: adds a lot of redundant code since the scale will likely not change during runtime.
2) Scale each sprite during editing. Pros: easy to do. Cons: have to remember to scale each sprite for the game, but keep a low-res copy for any other editing.
3) Scale during build time. Pros: awesome. Cons: none? :)

As you can guess by the title of the post, I went with #3. I figured this would let me still draw and save each sprite as tiny little images (tiles are currently 10×10 and the ninja just slightly larger) and still have them nice and large in the game. I’ll now share some code with you in case this is something you’d want to do.

First I created a new content pipeline extension project and added a reference in my game’s content project. Next I added a basic class that will define any constants I might need as time moves on. For now, it’s just one:

public static class Constants
{
	public const int Scale = 4;
}

Currently I’m scaling everything up 4x, but this lets me change one number and instantly get the game at a new scale.

Next I wrote up a quick and dirty texture importer. Since I didn’t feel like dealing with initializing D3D like the standard XNA TextureImporter class, I added a reference to System.Drawing and just used those APIs instead. Ultimately this is a pretty basic class. We load a bitmap and then copy over the pixels into a new PixelBitmapContent object which we then use as the first item in the mipmap chain.

[ContentImporter(DisplayName = "Texture - Ninja!")]
public class NinjaTextureImporter : ContentImporter<TextureContent>
{
	public override TextureContent Import(string filename, ContentImporterContext context)
	{
		Bitmap bitmap = Bitmap.FromFile(filename) as Bitmap;

		// XColor is an alias for Microsoft.Xna.Framework.Graphics.Color
		PixelBitmapContent<XColor> bitmapContent = new PixelBitmapContent<XColor>(
			bitmap.Width * Constants.Scale,
			bitmap.Height * Constants.Scale);

		for (int x = 0; x < bitmap.Width; x++)
		{
			for (int y = 0; y < bitmap.Height; y++)
			{
				// DColor is an alias for System.Drawing.Color
				DColor pixel = bitmap.GetPixel(x, y);
				XColor xPixel = new XColor(pixel.R, pixel.G, pixel.B, pixel.A);

				for (int x2 = x * Constants.Scale; x2 < (x + 1) * Constants.Scale; x2++)
				{
					for (int y2 = y * Constants.Scale; y2 < (y + 1) * Constants.Scale; y2++)
					{
						bitmapContent.SetPixel(x2, y2, xPixel);
					}
				}
			}
		}

		Texture2DContent texture = new Texture2DContent();
		texture.Faces[0] = new MipmapChain { bitmapContent };
		return texture;
	}
}

And there you go. Head back to the game content, choose this importer for my sprites, and like magic all of my sprites are scaled up for me. And since I’m handling the scaling, it’s all done with no interpolation so my pixels are nice and crisp.

The nice corollary to this experiment is that now I (and you for reading this post) know how to make a texture importer, meaning that the possibilities are endless. You could start loading in any image format supported by System.Drawing or use any other imaging system. As long as you can pack those into the PixelBitmapContent, you’re good to go.


Possibly Related Posts

(Automatically Generated)
Pixel Man Post Mortem #3
Pixel Man Post Mortem #2
Basic Handling of Multiple Controllers
Dynamically Refreshed Assets in XNA
Sprite Sheet Packer Tool – XNA GS Example

  1. March 10th, 2010 at 11:22
    Quote | #1

    I think I’m going to need to use this for my upcoming game… I was going to create everything at 320×180 and scale up with a matrix transformation, but (as you may already know), this causes the movement to be a bit jerky. I think your idea here will improve (fix) that… it will also be easier to think about the game in terms of 1280×720 screen resolution too.

  2. June 8th, 2010 at 03:13
    Quote | #2

    Hi Nick,

    I’ve been waiting for a new post dude, what’s happening?
    I hope you are just busy and nothing bad happened.

    -Peace.

Comments are closed.