Fun with External Text
AS3: Main
Using: AS3, any text editor, Cutscene.xml
You should be familiar with the file format you choose to use.
External text files are used by me to centralize a lot of data that might need editing. Specifically, it's easier for me to edit things when there isn't a bunch of code to sift through. This tutorial will apply to any external text format (XML, JSON, txt, etc), but I have the most experience with XML.
Why do you need them?
For my most recent game and another that I'm working on now, I've been using XML files to script cutscenes. I'm also using it to store the types and locations of enemies and allies. The point is, if you have lots of hard-coded numbers, strings, positions, etc, you should consider an external text file.
Embedding
No matter what format you use, all simple text files (things notepad can make) are streams of bytes (octets). So the embed tag will always be the same:
[Embed(source="filename.fileformat", mimeType="application/octet-stream")]
private const MY_TEXT_FILE:Class;
When you instantiate MY_TEXT_FILE, the result is a ByteArray(Asset). From here, it differs on how to get the data out. AS3 has native XML handling (E4X): you create a new XML object and pass the ByteArray as a parameter to be parsed to XML.
var x:XML = new XML(new MY_TEXT_FILE());
For JSON and regular txt files, you have to manually get the string out from the ByteArray using readUTFBytes.
var s:String = myBytes.readUTFBytes(myBytes.length); // where myBytes:ByteArray = new MY_TEXT_FILE()
If you're using a txt file, you're done, you have the string you wanted. For JSON, you have to parse the string to an Object.
var o:Object = JSON.parse(s);
Parsing data
This part will vary per format and per project. Maybe all you need one game is a list of comma separated values (csv/txt), maybe you need nodes and subnodes and attributes (XML, JSON). Whatever you choose, you will need to parse that data. For reference, everything in a text file is a String; every XML attribute is a String, the content is an XML, and the nodes are in an XMLList; JSON supports Number, Boolean, Object, Array, String, and null. For txt and XML, you will need to cast the data to get the type you actually want.
Since JSON gives you a native Object whose properties match up with the JSON file, it should be self-explanatory to find the data you want. For a txt file, you would use the split method of String to separate the comma (or any delimiter) separated values. Split returns an array of everything before, between, and after the commas. After that, you would use a combination of search, match, charAt, etc. to get to the data you want.
var example:Number = jsonObject.numberIWant;
var positions:Array = csvString.split(",");
To navigate XML, you have to realize that there is also the XMLList class, which is an array of XML. Each time you use the .childNode to go deeper into the XML, the value returned is an XMLList. You can use array access[] to get to the specific XML node you want. To access attributes, you put a "@" before the name of the attribute. If you try to access the attribute of an XMLList, it will concatenate the attributes of each node. You can also get all nodes with a specific attribute using E4X magic. The length FUNCTION of XMLList allows you to iterate over it like a normal array.
//<names>
// <n name="Nick" />
// <n name="MSGHero" />
// <n name="Nick" />
//</names>
var x:XMLList = names.n;
trace(x.@name, x[0].@name, x[1].@name, x.length, x.length()); // "NickMSGHeroNick","Nick","MSGHero",undefined,3 <-- "length()" is a function, "length" is just another node name
trace(x.(@name=="Nick"); // traces an XMLList containing nodes 0 and 2 since their attributes match the condition
When nodes and attributes don't actually exist, undefined is returned, not null or an error. To check if something is NOT undefined, you have to use "!=" rather than "!==" which I learned the hard way.
trace(x[0].@age, x[0].@name != undefined); // undefined,true
My level data XML is organized into rows of numbers, exactly like an array; I then loop through each row and look at each character to form the actual level array.
//<level id="0">
// <row>000</row>
// <row>011</row>
// <row>012</row>
//</level>
var rows:XMLList = level.row;
for each xml:XML in rows
var s:String = xml.toString()
for each character in the string
levelArray[i][j] = int(character); // level data, properties of an object, whatever you need