Sharp Serializer and XNA, Vector2 specifically

Category: windows phone howto

Question

Jared.Greiner on Wed, 21 Dec 2011 21:35:03


http://www.sharpserializer.com/en/index.html

SharpSerializer is an excellent way to save data in XML or binary formats.  I use it in my games to serialize custom objects with references to other custom objects, something that is difficult to accomplish with the standard XML Serializer.  I stumbled upon it after reading this article comparing methods of serialization on Windows Phone 7. 

http://www.eugenedotnet.com/2010/12/windows-phone-7-serialization-comparison/
 
The silverlight version of SharpSerializer works on Window's phone, but it is not designed to work with the XNA framework.  Specifically it will return Vector2's and many other variables as blank (0,0) upon deserialization.  After deciphering this page in German, I understood how to extend SharpSerializer to treat Vector2's and other XNA classes as "Simple Types".

http://florian.eagle-eye-studios.net/2011/04/sharpserializer-und-vector2/

In the Core/Tools.cs class I extended the "IsSimple" method as shown below:

public static bool IsSimple(Type type)  
{  
    // Lots of other code not show here that  
    // is in SharpSerializer by default  
 
    if (type == typeof(Vector2))     
    {     
        return true;     
    }     
    if (type == typeof(Rectangle))     
    {     
        return true;     
    }  
       
    return type.IsPrimitive;  


In the Advanced/SimpleValueConverter.cs class I extended the "ConvertFromString" method as shown below:

if (type == typeof(Vector2))  // A Vector2 is made up of an X and Y value
{                             // The deserialized string might look like
    int xValue = 0;           // {X:12 Y:45} or {X:0.375 Y:1.125}
    int yValue = 0;  
 
    Boolean convertToF = false;  // I assume that the Vector2 is int until I detect at decimal
    float xValueF = 0;  
    float yValueF = 0;  
                      
    //remove braces  
 
    var array = text.ToCharArray();  
    string xString = "0";  
    string yString = "0";  
    Boolean space = false;  
    for (int i = 0; i < array.Length; i++)  
    {  
        if (array[i] != '{'  
            && array[i] != 'X'  
            && array[i] != ':'  
            && array[i] != 'Y'  
            && array[i] != '}'  
            )  
        {  
            if (array[i] == '.')  // If I detect a decimal, then I know this Vector2
            {                     // contains floats
                convertToF = true;  
            }  
            if (!space)
            {  
                if (array[i] == ' ') // When I detect a space char, I know I am
                {                    // now looking at the Y value
                    space = true;  
                }  
                else 
                {  
                    xString = xString + array[i].ToString();  
                }  
            }  
            else 
            {  
                yString = yString + array[i].ToString();  
            }  
        }  
    }  
    if (!convertToF)  
    {  
        xValue = int.Parse(xString);  
        yValue = int.Parse(yString);  
        return new Vector2(xValue, yValue);  
    }  
    else 
    {  
        xValueF = float.Parse(xString);  
        yValueF = float.Parse(yString);  
        return new Vector2(xValueF, yValueF);  
    }  
}  
 
if (type == typeof(Rectangle))  // A rectangle is made of a position (X, Y) and dimension (Width, Height)
{                               // The deserialized string might look like {X:55 Y:68 Width:128 Height:256}
    int xValue = 0;  
    int yValue = 0;  
    int widthValue = 0;  
    int heightValue = 0;  
 
    string xRString = "0";  
    string yRString = "0";  
    string widthRString = "0";  
    string heightRString = "0";  
 
    int spaceCount = 0;  
 
    //remove braces  
    var array = text.ToCharArray();  
    for (int i = 0; i < array.Length; i++)  
    {  
        if (array[i] != '{'     // Remove braces "{" "}" and the
            && array[i] != 'X'  // "Height" and "Width" chars
            && array[i] != ':'  // ":"
            && array[i] != 'Y'  
            && array[i] != 'W'  
            && array[i] != 'i'  
            && array[i] != 'd'  
            && array[i] != 't'  
            && array[i] != 'h'  
            && array[i] != 'H'  
            && array[i] != 'e'  
            && array[i] != 'g'  
            && array[i] != '}'  
            )  
        {  
            switch (spaceCount)  
            {  
                case 0:  
                    if (array[i] == ' ')  // Each time a char == a blank space
                    {                     // we know that a we are reading a new value
                        spaceCount++;  
                    }  
                    else 
                    {  
                        xRString = xRString + array[i].ToString();  
                    }  
                    break;  
                case 1:  
                    if (array[i] == ' ')  
                    {  
                        spaceCount++;  
                    }  
                    else 
                    {  
                        yRString = yRString + array[i].ToString();  
                    }  
                    break;  
                case 2:  
                    if (array[i] == ' ')  
                    {  
                        spaceCount++;  
                    }  
                    else 
                    {  
                        widthRString = widthRString + array[i].ToString();  
                    }  
                    break;  
                case 3:  
                    heightRString = heightRString + array[i].ToString();  
                    break;  
            }  
        }  
    }  
 
    xValue = int.Parse(xRString);  
    yValue = int.Parse(yRString);  
    widthValue = int.Parse(widthRString);  
    heightValue = int.Parse(heightRString);  
                      
    return new Rectangle(xValue, yValue, widthValue, heightValue);  

Both the deserialization of Vector2 and rectangle work by turning the XML string value into a char array, then iterating through the array and assembling new separate strings to represent the individual values of the type.  These values are then parsed into ints or floats as needed.  The Vector2 deserialization can handle a Vector2 with two floats as well as one with two ints.  It properly handles values with several digets.  The rectangle deserialization requres all ints.

I'm open to suggestions on how to improve my code.  I'm really a novice programmer with no formal education in computer science.  I'll also check back to answer questions, so throw them my way.

Replies

sir pawian on Fri, 27 Apr 2012 06:12:38


hi Jared, on the following page you can compare your results with another solution which also works.
http://florian-vick.de/2011/04/sharpserializer-und-vector2/

it's german page but c# example is english ;-)