65.9K
CodeProject is changing. Read more.
Home

C# SpriteSheet Reader & Parser

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (1 vote)

Sep 1, 2012

CPOL
viewsIcon

14200

Code to read and parse a spritesheet coordinates file and extract the corresponding sprites from it

Introduction

This brief code is meant to read and parse a spritesheet coordinates file and extract its corresponding Image objects. I wrote it to be able to use spritesheets generated with TexturePacker and may be compatible with other tools.

Background

A spritesheet is an Image which contains smaller images like a map, to be used especially in games.

What is a sprite sheet?

Using the Code

A small class called Spritesheet with a static factory method LoadSpriteSheet to parse a coordinates (XML) file.

It holds a Dictionary to map the spriteFrameName to the actual Image it represents.

class Spritesheet
    {
        public string Name { get; set; }
        public Dictionary<string, Image> Sprites { get; set; }

        public Spritesheet(string spriteSheetName)
        {
            this.Sprites = new Dictionary<string, Image>(50);
            this.Name = spriteSheetName;
        }

        public static Spritesheet LoadSpriteSheet(string coordinatesFile)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(coordinatesFile);
            XmlNode metadata = doc.SelectSingleNode("/plist/dict/key[.='metadata']");
            XmlNode realTextureFileName = 
            metadata.NextSibling.SelectSingleNode("key[.='realTextureFileName']");
            string spritesheetName = realTextureFileName.NextSibling.InnerText;
            Image spriteSheetImage = Image.FromFile(spritesheetName);
            XmlNode frames = doc.SelectSingleNode("/plist/dict/key[.='frames']");
            XmlNodeList list = frames.NextSibling.SelectNodes("key");

            Spritesheet spritesheet = new Spritesheet(coordinatesFile);

            foreach (XmlNode node in list)
            {
                XmlNode dict = node.NextSibling;
                string strRectangle = dict.SelectSingleNode
                ("key[.='frame']").NextSibling.InnerText;
                string strOffset = dict.SelectSingleNode
                ("key[.='offset']").NextSibling.InnerText;
                string strSourceRect = dict.SelectSingleNode
                ("key[.='sourceColorRect']").NextSibling.InnerText;
                string strSourceSize = dict.SelectSingleNode
                ("key[.='sourceSize']").NextSibling.InnerText;
                Rectangle frame = parseRectangle(strRectangle);
                Point offset = parsePoint(strOffset);
                Rectangle sourceRectangle = parseRectangle(strSourceRect);
                Point size = parsePoint(strSourceSize);

                string spriteFrameName = node.InnerText;
                Image sprite = new Bitmap(size.X, size.Y);
                Graphics drawer = Graphics.FromImage(sprite);
                drawer.DrawImage(spriteSheetImage, sourceRectangle, frame, GraphicsUnit.Pixel);
                drawer.Save();
                drawer.Dispose();
                spritesheet.Sprites.Add(spriteFrameName, sprite);
            }
            return spritesheet;
        }

        private static Rectangle parseRectangle(string rectangle)
        {
            Regex expression = new Regex(@"\{\{(\d+),(\d+)\},\{(\d+),(\d+)\}\}");
            Match match = expression.Match(rectangle);
            if (match.Success)
            {
                int x = int.Parse(match.Groups[1].Value);
                int y = int.Parse(match.Groups[2].Value);
                int w = int.Parse(match.Groups[3].Value);
                int h = int.Parse(match.Groups[4].Value);
                return new Rectangle(x, y, w, h);
            }
            return Rectangle.Empty;
        }

        private static Point parsePoint(string point)
        {
            Regex expression = new Regex(@"\{(\d+),(\d+)\}");
            Match match = expression.Match(point);
            if (match.Success)
            {
                int x = int.Parse(match.Groups[1].Value);
                int y = int.Parse(match.Groups[2].Value);
                return new Point(x, y);
            }
            return Point.Empty;
        }
    } 

Here is a usage example:

OpenFileDialog dialog = new OpenFileDialog();
dialog.Filter = "property list (*.plist)|*.plist|XML files (*.xml)|
*.xml|Supported Files|*.xml;*.plist";
dialog.FilterIndex = 3;
if (dialog.ShowDialog(this) == DialogResult.OK)
{	
	Spritesheet spritesheet = Spritesheet.LoadSpriteSheet(dialog.FileName);
	//TODO
} 

History

  • Initial post, basic usage guidelines

Note: Doesn't support sprite rotation, yet!