Click here to Skip to main content
15,885,757 members
Articles / Programming Languages / C#
Tip/Trick

C# SpriteSheet Reader & Parser

Rate me:
Please Sign up or sign in to vote.
4.00/5 (1 vote)
31 Aug 2012CPOL 13.9K   8   1
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.

C#
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:

C#
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!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Mexico Mexico
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 4 Pin
Christian Amado2-Sep-12 5:09
professionalChristian Amado2-Sep-12 5:09 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.