Friday, June 26, 2009

Embedding XML in AS3

I thought I'd write a bit of a technical post for a change, explaining how to embed XML files in a SWF from FlashDevelop. Coincidentally, I used XML to store the layout of MoneySeize's stages, so the example will specifically be geared toward XML representing platformer stages.

Now then, here's an example of an XML stage file from MoneySeize. It's actually just a snippet of a stage file, not a full one:

< STAGE>
< OBJECTS>
< BLOCK X="2" Y="23" WIDTH="36" HEIGHT="4" />
< SPAWN X="6" Y="22" />
< BLOCK X="12" Y="21" WIDTH="4" HEIGHT="2" />
< TUTORIAL X="18" Y="16" TEXT="..." />
< TUTORIAL X="28" Y="22" TEXT="..." />
< BLOCK X="36" Y="2" WIDTH="2" HEIGHT="16" />
< JUMPTHRU X="32" Y="9" WIDTH="4" />
< BLOCK X="27" Y="9" WIDTH="5" HEIGHT="2" />
< COIN X="28" Y="7" />
< COIN X="30" Y="7" />
< COIN X="32" Y="7" />
< COIN X="34" Y="7" />
< BLOCK X="17" Y="8" WIDTH="5" HEIGHT="2" />
< BLOCK X="2" Y="9" WIDTH="10" HEIGHT="2" />
< CHEST X="19" Y="7" COINS="5" />
< DOOR X="5" Y="8" />
< BLOCK X="37" Y="20" WIDTH="2" HEIGHT="3" />
< BLOCK X="1" Y="5" WIDTH="3" HEIGHT="4" />
< BIRD_GOLD X="2" Y="4" COINS="3" TIME="5" />
</ OBJECTS>
</ STAGE>

The XML is pretty self-explanatory. As you can see, the stage contains an objects tag, which contains a list of every game object on the stage. Objects include blocks, coins, "tutorials", "jumpthrus" (one-way blocks), etc. Each object tag includes its x and y positions (divided by 16, because the game is grid-based) and any other applicable attributes (for example the CHEST tag contains a COINS attribute to indicate the amount of coins in the chest).

Of course, designing levels by typing raw XML into a text file isn't very intuitive, so it's nice to have an editor.

So now that we have the XML, our goal is to embed it in our SWF. Then, at some point as the game is running, we will load and parse it to build the level it represents. Here's the code I used to embed the XML:

public class Levels 
{
[Embed(source='../../../assets/levels/Level1.xml',
mimeType="application/octet-stream")]
public static const Level1:Class;
}

The "application/octet-stream" MIME type allows us to embed any asset as a byte stream. The last step is to load the XML into memory and parse it:

var file:ByteArray = new Levels.Level1;
var str:String = file.readUTFBytes( file.length );
var xml:XML = new XML( str );

Here we load the level as a ByteArray, then convert it to a string. This string is the raw XML of the file in string format, which we can use to create an XML object. Now we use the interface of the XML object to parse the level data:

var o:XML;
for each (o in xml.OBJECTS[0].BLOCK)
{
addChild( new Block( o.@X, o.@Y, o.@WIDTH, o.@HEIGHT ) );
}

For MoneySeize, it is known that each level file only has one OBJECTS tag, so we can simply access xml.OBJECTS[0] to find all the game objects. xml.OBJECT[0].BLOCK is another XML object: it contains every BLOCK tag within the OBJECTS tag. We simply traverse every tag in the object, adding a block object to the level for every BLOCK tag.

Note that the @ symbol is used to access the attributes within a tag.

Labels: ,

7 Comments:

Blogger Wes said...

I like building levels using text files and a custom parser, and XML is a great solution. Does your editor build the XML file as you design, or do you just hit Build when you're done and it runs through the level to generate the code?

June 27, 2009 3:16 AM  
Blogger James K. said...

haha! I was going to say. When first reading that, I was like "You manually place EVERYTHING?!" But them you mentioned the editor you built.

June 27, 2009 11:13 AM  
Blogger Matt Thorson said...

I hit Build when I'm done, and the editor spits out the XML as well as a backup file which it can read to edit the level later.

June 27, 2009 12:21 PM  
Blogger ChevyRay said...

Haha

Thanks, Matt! Made perfect sense. I'll actually try getting this working later today, as it looks pretty simple.

You're a bro. :D

June 27, 2009 4:30 PM  
OpenID zabijaciel said...

This is perfect, basically you never have to load a static XML file as long as you re-build your SWF whenever you modify it, which seems like a good deal to me! Thanks for the post.

July 21, 2009 11:51 AM  
Blogger Oldschool said...

I've seen the code for this before, but it makes a lot of sense here. I came here from your link in tigsource. It seems the guy that made the sprite library I use saw your post over there too and used your xml technique in his sprite library at adventuresinactionscript dot com. Thanks!

October 27, 2009 9:43 AM  
Blogger Actionscript said...

Not unless i've got a time machine as i posted my code may 08 :) It's just the normal way to access embedded xml, nothing fancy - but it is a simple straight forward tut and info on an editor so props to matt (i never did release my flex based animated sprite cutter!).

November 26, 2009 10:15 AM  

Post a Comment

<< Home