So I was messing around with some of (famous artist) Kenney's art assets this morning.
His sprite sheets consist of an image, plus an XML file that looks like this:
<TextureAtlas imagePath="medievalRTS_spritesheet@2.png">
<SubTexture name="medievalEnvironment_01.png" x="1029" y="636" width="38" height="92"/>
<SubTexture name="medievalEnvironment_02.png" x="1030" y="728" width="37" height="66"/>
<SubTexture name="medievalEnvironment_03.png" x="1023" y="0" width="53" height="96"/>
<SubTexture name="medievalEnvironment_04.png" x="838" y="736" width="28" height="30"/>
We don't have a general XML parser at this point (though we do have them for JSON and GRFON). But I hacked something out that works well enough for this data.
First, a function to parse out a single XML node's ID and attributes:
// Parse out the attributes of an XML element. Example:
// given: <Foo name="Apple" weight="23"/>
// returns: {"_id":"Foo", "name":"Apple", "weight":"23"}
parseXMLAttributes = function(line)
line = line.trim
if line.len < 3 or line[0] != "<" or line[-1] != ">" then return null
if line[-2] == "/" then line = line[1:-2] else line = line[1:-1]
parts = line.split
result = {"_id":parts[0]}
for part in parts[1:]
eqPos = part.indexOf("=")
if eqPos < 0 then
result[part] = true
else
// we'll use json.parse to parse the value string
// (since JSON and XML are close enough in this regard)
result[part[:eqPos]] = json.parse(part[eqPos+1:])
end if
end for
return result
end function
(requires import "stringUtil"
and import "json"
at the top of the program course).
...Then, a function that parses out an entire sprite sheet:
// Load a sprite sheet as defined by an XML file in the
// style of Kenney's assets, i.e.: a TextureAtlas line
// at the top, followed by a bunch of SubTexture lines.
// (Note that this is not a general XML parser.)
// Returns a map from sprite name (minuse the extention)
// to image.
loadImagesFromXML = function(path)
result = {} // key: sprite name; value: Image
for line in file.readLines(path)
attrs = parseXMLAttributes(line)
if attrs == null then continue
if attrs._id == "TextureAtlas" then
sourcePic = file.loadImage("/usr/pics/" + attrs.imagePath)
continue
end if
if attrs._id != "SubTexture" then continue
name = attrs.name - ".png"
left = val(attrs.x)
width = val(attrs.width)
height = val(attrs.height)
bottom = sourcePic.height - val(attrs.y) - height
img = sourcePic.getImage(left, bottom, width, height)
result[name] = img
end for
return result
end function
Sample usage:
sheet = loadImagesFromXML("/usr/pics/medievalRTS_spritesheet@2.xml")
view sheet.medievalEnvironment_20
Pretty neat! Feel free to use this code in your own projects whenever you need to load a sprite sheet like these.