Serialization

The GameBuilder Engine uses XML to store data about a game's objects. This chapter describes the format the engine expects when instantiating objects from XML. Loading XML object descriptions and instantiating them is handled by the TemplateManager class.

XML Format Overview

The easiest way to explain GameBuilder Engine's XML serialization format is to go through an example. Later sections provide a reference to specific details of the format. Here is an example level with explanatory comments:

<!-- Root tag - indicates version in case there are breaking changes  in the format. The root tag contains one or more entities, templates or groups.-->


   <!-- Only one entity of a given name can exist in the world at a time. The TemplateManager will generate warnings if you instantiate them more than once. -->
   
   
      <!-- Entities and templates contain components, which are named and have a specified type. -->
      
         
         <!-- Fields on the component are dealt with using our normal  serializer. In this case we are assigning a string to  ImageFilename on the SpriteSheetComponent. -->
         ../Assets/Images/platform.png
      
   
   
   <!-- Another sprite sheet - just the same as the above one, but with a  different entity name and file. -->
   
      
         ../Assets/Images/guy.png
      
   
   
   <!-- Templates are like entities in every respect except two. First, they can be instantiated more than once w/o warnings. Second, they can be referenced via the template attribute on an entity, which is explained later. -->
   
   
   
      
         
            400
            300
         
      
   
   
   
      
      
      
         
      
   
   
   
      
         <!-- In addition to componentReference, you can specify componentName, which indicates a specific component to reference. -->
              
         <!-- If you use componentName alone, it will reference that component on the owning entity. -->
         
         
         @Spatial.position
         @Spatial.rotation
         @Spatial.size
         true
      
      
         
         
            Dude
         
         
            Platform
         
         
            400
            100
         
         
            64
            74
         
         false
         false
         
            <_ type="com.pblabs.box2D.CircleCollisionShape">
               0
               0.5
               00.5
            <!--_-->
         
      
      
         @Spatial.LinearVelocity
         <!-- Input Map Example -->
         <input>
            LEFT
            RIGHT
            UP
         
      
   
   
   <!-- Often you want one entity to be a clone of another with minor  modifications. You can do this via the template attribute. Everything on Platform is loaded into the entity, then the information in the Platform1 entity is applied on top of it. -->
   
      <!-- Notice that when we reference fields for an existing component 
           (from the template) we omit the type attribute. -->
      
         
            94
            450
         
      
   
   
   
      
         
            400
            500
         
      
   
   
   
      
         
            706
            450
         
      
   
   
   <!-- Groups are lists of templates/entities, so that you can instantiate them all as a single group. TemplateManager.InstantiateGroup returns an array of all the objects that were created. -->
   
      <!-- Group tags contain one or more objectReference or groupReference tags. These reference groups or entities/templates by name, indicating what is part of the group. Things can be part of any number of groups. -->
      <objectreference name="Scene">
      <objectreference name="Box2D">
   </objectreference></objectreference>
   
   
      <objectreference name="DudeSpriteSheet">
      <objectreference name="PlatformSpriteSheet">
   </objectreference></objectreference>
   
   
      <objectreference name="Dude">
      <objectreference name="Platform1">
      <objectreference name="Platform2">
      <objectreference name="Platform3">
   </objectreference></objectreference></objectreference></objectreference>
   
   
      <!-- This is how you reference a group from inside another group. -->
      
      
      
   
   

Basic Structure

There are three types of objects that can be instantiated from XML using the engine's TemplateManager class. These are entity, template, and group. Each of these can appear any number of times in a single XML file, in any order. They are all contained in the same parent tag that is the root of the XML document.

When an XML file is loaded, everything inside the root tag is added to the TemplateManager for later instantiation. Keep in mind, merely loading a description of an object does not actually create that object. It must be instantiated manually with the TemplateManager.

Entities

The entity tag contains the XML for an IEntity object. An IEntity is essentially a named container for a collection of components. So, the entity tag supports a single child tag, appropriately named component. Any number of component tags can be added to an entity tag, with each one describing a different component.

The name of the entity is set using the name attribute. Additionally, a template attribute is supported. The template attribute should be the name given to an XML object described with a template tag. The deserializer handles templates by first deserializing the new IEntity with the description contained in the template, then deserializing it again with the description contained in the entity. Essentially, this allows a template object to describe a common set of components for the IEntity, and the entity to overwrite or add additional components to the IEnity. The template attribute is optional.

Templates

A template is constructed in identical fashion to an entity, including the optional template tag. The only difference between a template and an entity, once instantiated, is that a template is not registered with the NameManager class, whereas an entity is. The reason for this is templates are designed to be instantiated multiple times, for things like bullets or respawning enemies, whereas an entity is designed to be instantiated once.

Entities cannot be used as templates in XML, however, so any object that is being used as a base description must be created as a template. Templates can be derived from other templates, though, with no limit on how many derivation levels there are.

Components

The component tag goes inside of either a template or entity tag and describes a component that should be added to that template or entity when it is instantiated.

The component tag has two attributes, both of which are required in the normal case (the other case will be described below). The first attribute is type, which specifies the fully qualified class of the component. So, for instance, a component with class DisplayObjectRenderer in the namespace com.pblabs.rendering2D would have its type attribute set to "com.com.pblabs.rendering2D.DisplayObjectRenderer".

The second attribute is name. This specifies the name to assign to the component when it is instantiated. A component's name must be unique across all components on the same entity as it is used to lookup the component on an entity.

The tags inside of a component correspond exactly to the properties of that component. If a component has a property Position, then that property's value can be set with a child tag called Position. More information on this is in the General Serialization section.

Component tags also have the capability of overwriting an existing component rather than instantiating an entirely new one. This would happen when templates are being used. If an entity derives from a template with a component named "MyComponent", that entity can also have a component with name "MyComponent". Instead of creating another instance, the existing component on the template is looked up and its properties are replaced with anything defined by the child component. In this case, the child component should not have a class attribute.

Groups

A group is the third type of object that can be described in XML. It is essentially just a list of other templates, entities, or groups that will all be instantiated when the group is instantiated. For example, if you define a group with two children "MyFirstEntity" and "MySecondEntity", instantiating the group will instantiate both of those entities.

The list of objects to instantiate can contain two different tags. The first is objectReference, which is used for both templates and entities. The second is groupReference, which is used for referencing other groups.

A group has no effect on the actual game once instantiated. It is merely a convenience for instantiating several objects at once.

General Serialization

Component tags can contain any number of child tags that correspond to their properties as defined in code. If a component has a public property named "MyProperty", it's value can be set to 7 by adding <MyProperty>7</MyProperty> as a child of the component tag.

If a component has a class property that has child properties itself, these can be set as well. For example, to set the value of a Point property called Position, use the XML:


   10
   25

Additionally, classes can contain child classes as well, to an infinite depth, using the same method.

By default, the deserialization process will automatically infer the type of the class to create based on the type specified in your code. You can override this behavior using the type attribute. This would allow you to instantiate a subclass of a class that was expected. The type attribute requires a fully qualified class name.

Class References

Properties that store references to IEntity objects or IEntityComponent objects can also be resolved in the XML. This is done with the entityReference, entityName, and objectReference attributes.

The nameReference attribute is used to assign a reference to an existing IEntity to the property. So, it must be the name of an entity that has already been instantiated. The property type should be IEntity and is resolved before onAdd is called on any components.

objectReference works the same way as nameReference, but instead of looking up an existing object, it will instantiate it from a named template instead.

The entityName attribute also takes the name of an existing entity, similar to the nameReference. The correct component is retrieved from the entity by inferring the type of component the property expects and looking up a component of that type from the found entity. An additional attribute can be specified to look up a specific component on the entity. This is the componentName attribute and should be set to the name of the component to lookup.

Arrays and Dictionaries

Arrays and Dictionaries are handled in almost the same way by the deserializer. The only difference is Arrays can use default tags to push objects onto them, whereas Dictionaries require a key.

The type of object that is added to a Dictionary or Array is specified by the childType attribute. This attribute value is the default type that will be used when instantiating child tags. Each child tag can optionally include the type attribute to override the type specified by the childType attribute.

The tag for each child corresponds to the key in the dictionary or array that the object will be added to. The handling of this key value has some special rules, however. To begin with, if the key has a leading underscore, it is automatically removed. This is to allow for keys that are just numbers as the XML specification does not allow numbers to be tags. If the key consists of just an underscore, the instantiated class is simply pushed onto the back of the array. For dictionaries, a single underscore is considered invalid.

Custom Serialization

The XML format for every class is as described in the General Serialization section, unless the class implements the ISerializable interface. If this is the case, the format can be anything, since it is defined by the specific ISerializable implementation. The built in classes that implement this are PropertyReference, ObjectType, and InputMap.

PropertyReference fields can be treated exactly like strings. The string value is that is set in XML is set as the value of the PropertyReference.

ObjectType fields can be treated like an array of strings. Each of the child tag values is added as a named type to the ObjectType field.

The InputMap class can be treated exactly like a dictionary. The keys should be the name of a binding on the input map, and the value should be the name of the key to use for that binding.

Loading a Level File

To load a level file you use the LevelManager. It's job is to manage the loading and unloading of level files. It also provides an interface to add and remove file and group references. You can also override the default file loading and unloading methods to customize this behavior

Creating A Level File


  
    
    
    
  

Each level that you want to load into your game needs to be defined in a LevelDescriptor xml file. Create a level xml node <level> and give it an index. You can define the group names and the level file location that contains all of the entity and template definitions for that level.

In the code below you load the level descriptor file using the Level Manager and specify the level you want to auto load. Passing a value of -1 will only load the file and not load the actual level. You can load the level you want later by calling loadLevel().

LevelManager.instance.addEventListener(LevelEvent.LEVEL_LOADED_EVENT, onLevelLoaded); 
LevelManager.instance.load("levels/LevelsDescriptor.xml", 0);

protected function onLevelLoaded(event : LevelEvent):void 
{
     //Implement if needed
}

Loading via ActionScript

As one would expect, the process of loading level files in ActionScript is very similar to doing so with xml.

// Add file and group references
LevelManager.instance.AddFileReference(0, "../Assets/Levels/level.pbelevel");
LevelManager.instance.AddGroupReference(0, "Managers");
LevelManager.instance.AddGroupReference(0, "SpriteSheets");
LevelManager.instance.AddGroupReference(0, "Objects");
LevelManager.instance.AddGroupReference(0, "Everything");

// Load level 0 and start game.
LoadManager.instance.LoadLevel(0);
LoadManager.instance.Start();

Serializing Any Class With the Serializer

//You can pass any class to the Serializer and it will travers the class and serialize its contents to an xml format.
var dataObject : Object = {};
dataObject.position = new Point();
dataObject.customNumber = 10;

var xml : XML = new XML('');
Serializer.instance.serialize(dataObject, xml);

This chapter has described the XML format assuming level files and the TemplateManager are being used to load and instantiate the XML data. This does not have to be the case. The Serialization class provides all the functionality necessary to instantiate any class from an XML description, or serialize any existing class to an XML description. The format outlined in this chapter still applies, but the Serialization class is used directly, rather than loading level files with the TemplateManager.

Complete Tag List

  • things: The root tag.
  • template: A child of the root tag, specifying that the contained XML is a template definition.
  • entity: A child of the root tag, specifying that the contained XML is an entity definition.
  • group: A child of the root tag, specifying that the contained XML is a group definition.
  • component: A child of the template or entity tag, specifying that the contained XML is a component definition.
  • objectReference: A child of the group tag, specifying the name of a template or object to instantiate with the group.
  • groupReference: A child of the group tag, specifying the name of a group to instantiate with the parent group.

Complete XML Attribute List

  • name:

On template tags, it specifies the name of the template.
On entity tags, it specifies both the name of the entity in XML, and the name of the object that is instantiated from it.
On group tags, it specifies the name of the group.
On component tags, it specifies the name of the component once registered with its owning IEntity.
On objectReference tags, it specifies the name of the template or entity to reference.
On groupReference tags, it specifies the name of the group to reference.

  • template: Exists on a template or entity tag and specifies the name of a template to inherit component definitions from.
  • nameReference: Specifies the name of an entity to lookup and set on the tag.
  • objectReference: Specifies the name of a template or entity to instantiate and set on the tag.
  • entityName: Specifies the name of a template or entity to lookup and search for a compatible component to set on the tag.
  • w: Specifies the name of a component to reference. If used without a componentReference attribute, the component is looked up on the same entity that this attribute is a part of.
  • type:

On a component, specifies the fully qualified type to use to instantiate the component.
On a field, specifies the type to use when instantiating the field for the parent tag.

  • childType: Specifies the type to use when instantiating objects to add to an array or dictionary.
  • filename: For fields that hold resources, this lets you specify a file path. The field must be of a compatible type to the type of the resource as specified to the resource manager. The resource will be loaded and assigned to the field.

Follow Us For Updates