Creating Moddable Games with XML and Scripting Part I
Roadmap for the series
This series will span the development of a small game, "jsInvaders" and focus solely upon creating and embedding the script and XML parsing interfaces that serve as a facility to modify (mod) the content and behaviours within the game.
To follow this series, I am assuming that you have knowledge of C++, OpenGL and understand the principles of game creation. This series is not a game creation tutorial, so I will not be focusing on normal game aspects such as graphics, sound, game logic, et al. Here's a brief outline of how you can expect this series to progress:
Brief Introduction to XML
Now that you understand where this series will be headed, I will now introduce you to the basics of XML documents. After reading this section, you should understand exactly what XML is, how to create it and be thinking of ways you can apply XML to your games. I suggest that you read Richard Fine's "XML in Games" available on GameDev.net, as it serves as an excellent introductory text on the subject.
The XML document specifications require each valid document to begin with an XML file declaration:
<?xml version="1.0" encoding="utf-8"?>
Quite simply, this declaration is stating that the document is XML version 1.0 and is encoded with the UTF-8 character set.
XML is a meta-language; in short you are able to define your own set of tokens (or 'tags'), rules and structures. Most XML files are defined by a DTD, or Document Type Definition which dictates the rules and structure of the document by supplying a list of legal tokens. DTD rule creation is important as it allows the XML parser to quickly accept or reject documents on loading. With that said, we are using TinyXml and it is a non-validating parser; it will ignore any DTD it finds and just processes the document elements with no rules. This is fine for our purposes as we can build our own validation rules into the parsing stage.
XML documents have a strict hierarchical structure; elements are contained within other elements, which in turn are contained within higher elements in the document tree. This tree-like structure needs a root, the document root, and is the single element which all other elements are descended from. Every element on the next hierarchical level is called a child of an element and elements with the same root element are said to be siblings.
The hierarchical structure of XML allows for easy parsing of the tree and can introduce great flexibility when it comes to manipulating the data. Whole branches can be detached and placed elsewhere with little difficulty.
Let's take a look at a basic declaration of a jsInvaders level:
<?xml version="1.0" encoding="utf-8"?> <invadersgame> <level> <alien /> <alien /> <alien /> </level> </invadersgame>
You should be able to see that the document root element is <invadersgame>. The root then contains a level element, which in turn contains three alien elements. In order to clarify this, I'll break down the basic jsInvaders level document:
If you're used to Object Oriented Programming (OOP), then you'll probably be able to picture how you'd map these elements into classes. By referring to the code attached to this article, you'll see how I've begun mapping these objects into C++ classes for use in the game. So far in the code I have the game classes sketched out for dealing with levels, aliens and the player ship. I won't go into detail about much of the rest of the game classes as it is beyond the scope of this article.
If you examine the file jsiAlien.h, you'll see that I have defined several properties for the object. Things like 'color', 'position' and 'points value' are all properties of the Alien object that will need values to be of use in the game. XML document elements can also have attributes assigned to them, meaning that you can represent the data for objects such as the Alien object with an XML element tag.
<alien xpos="0" ypos="100" color="red" points="10" />
If you look at the declaration above you will see that I have assigned 4 properties to the XML element that represents the Alien. In this example the alien is red, is positioned at (0, 100) and awards 10 points to the player when killed. Taking this forward, we begin to build the XML file that defines a basic game level.
<?xml version="1.0" encoding="utf-8"?> <invadersgame> <level> <!-- here's where we declare the aliens --> <alien xpos="0" ypos="100" color="red" points="10" /> <alien xpos="100" ypos="100" color="green" points="10" /> <alien xpos="200" ypos="100" color="blue" points="10" /> </level> </invadersgame>
It should be apparent that we now wish to have 3 aliens of different colours, each 100 units apart horizontally. You'll notice that I've begun commenting my XML document with the XML comment tags, <!-- this is a comment -->. I personally find commenting all of my code to be good practice, even in this simple example :). The benefits of good commenting will reveal themselves later on when the files start getting bigger.