Click here to Skip to main content
Click here to Skip to main content

C# SpriteSheet Reader & Parser

By , 31 Aug 2012
Rate this:
Please Sign up or sign in to vote.

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!

License

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

About the Author

tochas
Software Developer (Senior)
Mexico Mexico
No Biography provided
Follow on   Twitter

Comments and Discussions

 
GeneralMy vote of 4 PinmemberChristian Amado2-Sep-12 5:09 

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

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

| Advertise | Privacy | Mobile
Web01 | 2.8.140421.2 | Last Updated 1 Sep 2012
Article Copyright 2012 by tochas
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid