Writing a Converter for the GLEED2D Level Editor

Working on a prototype means that if you can cut corners, you totally should. The goal of the prototype is to get a better understanding of your game while creating something that others can experience. For science. Creating maps for your game shouldn’t get in the way of actually making a compelling experience, and cutting corners here can be tough to pull off.

After doing some research online, I had come up with a list of possible matches for what I needed. Problem with this, however, is that good level editors cost money and usually come with a whole game engine. Also, I’m cheap, so there’s that. GLEED2D was really simple and exported to XML. Which was good, except the level format didn’t match the one I’ve been using. Fortunately, the program also comes with a setting that allows you to run an app when a map is saved and pass the file path to the application.

Armed with this feature, I started building a level converter that took in the GLEED2D level path, serialized it into their level format, copied values into my own level object, then serialized into a new XML file. Ridiculous, I know, but waaaay less time than actually coding my own level editor. What ended up taking me the longest was trying to figure out why my converter wasn’t taking the command line parameters (essentially the level path). Turns out I just had to make the app a console app and it worked fine!

*Technical Jargon Below*

If you are working in XNA, you can create an windows game project and set it’s properties to output a console application. OR you can just make a console application and be sure to include the required references to the XmlSerialization classes.

In the Program.cs file (assuming you’ve chosen the first path), you’ll want to make sure that the file path is passed along to your game loop. Mine looks like this:

 1 2 3 4 5 6 7 8 910
static void Main(string[] args) {
    string path = "";
    if ( args.Length == 1 ) {
        path = args[0];
    }

    using ( Game1 game = new Game1( path ) ) {
        game.Run();
    }
}

Now that the path is being passed through, you can load the file up, deserialize it, convert it, serialize the new file, and save that one out. You want to make sure that where you save the new file doesn’t overwrite the old one since the GLEED2D file also contains information that the editor itself needs.

 1 2 3 4 5 6 7 8 910
Type[] extendedList = { };

FileStream fileStream = new FileStream( path, FileMode.Open );
XmlDocument _CurrentLevelReset = new XmlDocument();
_CurrentLevelReset.Load( fileStream );
fileStream.Close();

//now deserialize the content
XmlSerializer ser = new XmlSerializer( typeof( Level ), extendedList );
Level level = ( Level )ser.Deserialize( new XmlNodeReader( _CurrentLevelReset.DocumentElement ) );

Level is the GLEED2D level type. I then create my own GameEngine.Level object (from my own format) and copy over values. If you create a level in the editor that has the properties and values you expect, you can go through and pick which elements will pass through to your custom level object. Once you’ve filled the custom level with the data you need, just serialize and save!

 1 2 3 4 5 6 7 8 9101112131415
// Input your special extra items in this list as typeof( Class )
Type[] extendedList2 = { };
ser = new XmlSerializer( typeof( Engine.Mapping.Level ), extendedList2 );
System.Text.StringBuilder sb = new System.Text.StringBuilder();
System.IO.StringWriter writer = new System.IO.StringWriter( sb );
ser.Serialize( writer, newLevel );
XmlDocument doc = new XmlDocument();
doc.LoadXml( sb.ToString() );

var splitPath = path.Split( '\\' );
String fname = splitPath.Last();
String newPath = path.Substring( 0, path.Length - fname.Length );
newPath +="Converted\\" + fname;
doc.Save( newPath );
this.Exit();

This will save all converted levels into a “Converted” folder in the same folder that the original level came from. Helps to keep things organized. This system is by no means the best option, but that best option would take way too much time and I was able to put this converter together in a matter of a couple hours.

Happy Converting!

And there you have it! The conversion code is really just taking variables from one object and passing them through to another.

githublinkedin