Roy Triesscheijn’s Weblog

My programming world

Science LinX Herschel Exhibit

Posted by Roy Triesscheijn on 19th June 2011

For Science LinX I’ve working on an exhibit regarding the ESA Herschel satellite for the last 6 months, and I’m happy to inform you that it’s almost complete.

Features

-Camera is moved by using multi-touch signals sent by monitor,
-Accurate simulation of our solar system, planets support properties like eccentricity, inclination, orbital radius, equatorial diameter,  rotations per earth-year, orbits per earth-year.
-Herschel satellite stationary in lagrange point L2.
-Fully 3D
-Multiple lighting effects
- Particle effects (not currently used)
-Beautiful skybox generated using Space Scape
-Expandable information boxes slowly center arc-ball camera on P.O.I.
-Twitter integration (following the @ESAHERSCHEL channel)
-Clickable planets, satellites and points of interests
-Multiple Zoom levels smoothly change information windows, ‘tunnel vision’.

Screenshots

Anyway, this all sounds exciting (or not) but it’s always better  to see it for yourself:

The Team
-Bart v/d Laar (Project Manager Science LinX)
-Ingeborg Veldman (Project Manager Science LinX Virtual)
-Hilbert Dijkstra (Project Designer, Text Writer)
-Roy Triesscheijn (Programmer)
-Hugo Engwerda (Artist)
-Gerwin Kramer (Modeler)
-Peter Barthel (Astronomer/Technical Consultant)

Tags: , , ,
Posted in Blog, General Coding, XNA | No Comments »

XNA stereoscopic 3D using anyglyphs and red/cyan 3D-glasses

Posted by Roy Triesscheijn on 8th May 2011

Anaglyphs are images designed to give a 3D effect when viewed with special glasses, usually with red and blue (sometimes red and cyan) filters over the left and right eyes, respectively.[1]


Using anaglyphs we can make our game look real 3D through those cheap red/cyan 3D-glasses. Adding an anaglyph effect to your XNA game is fairly easy.

Basically we need to undertake the following steps:
-Draw our scene twice to separate render targets, with a slightly offset camera
-Use a shader and draw a full screen quad to blend the images and color coding the images for each eye

Easy right!

Lets start by assuming you have the following draw code:

protected override void Draw(GameTime gameTime)
{
    //a lot of draw calls
    base.Draw(gameTime);
}

We need to extract all your drawing code (except base.Draw(..)) to a new method that as argument accepts a view matrix. Update your code so that the passed viewMatrix is used instead of your normal camera’s viewMatrix. Doing this will allow us to easily draw the scene twice with a slightly offset camera. You should now have something like this:

private void DrawForEye(Matrix viewMatrix)
{
    //...
}

Now let’s first write the shader that is going to blend the images, create a new effect in your content project and paste in the following code:

texture left;
sampler sLeft = sampler_state
{
	texture = ;
	magfilter = POINT;
	minfilter = POINT;
	mipfilter = POINT;
	AddressU  = CLAMP;
	AddressV  = CLAMP;
};

texture right;
sampler sRight = sampler_state
{
	texture = ;
	magfilter = POINT;
	minfilter = POINT;
	mipfilter = POINT;
	AddressU  = CLAMP;
	AddressV  = CLAMP;
};

struct VS_INPUT
{
	float3 Pos : POSITION;
	float2 Tex : TEXCOORD0;
};

struct VS_OUTPUT
{
	float4 Pos : POSITION;
	float2 Tex : TEXCOORD0;
};

void VtAnaglyph(VS_INPUT In, out VS_OUTPUT Out)
{
	Out.Pos = float4(In.Pos,1);
	Out.Tex = In.Tex;
}

float4 PxAnaglyph(VS_OUTPUT In) : COLOR0
{
    float4 colorLeft = tex2D(sLeft, In.Tex.xy);
	float4 colorRight = tex2D(sRight, In.Tex.xy);
    return float4(colorRight.r, colorLeft.g, colorLeft.b, max(colorLeft.a, colorRight.a));
}

technique Anaglyphs
{
    pass p0
    {
        VertexShader = compile vs_2_0 VtAnaglyph();
        PixelShader = compile ps_2_0 PxAnaglyph();
    }

}

This is a pretty standard HLSL shader, but I will quickly go over it.

The texture’s left and right will be the textures resulting from drawing the scene twice, slightly offset from each other. We use a sampler with POINT filters because the left and right textures are going to be exactly the same size as our final rendering.

The vertex shader is passed as input nothing more than the position and texture coordinate of the vertex, it doesn’t transform anything but it just directly passes to the pixel shader.

The pixel shader samples the textures for the left and right eye. The red channel is used to ‘encode’ the image for the right eye (the red is unfiltered by the cyan colored lens). The green and blue channel are taken from the image for the left eye (they are unfiltered by the red colored lens). You can look at this wikipedia entry for other color combinations in case you have different 3D-glasses.

Now that we have our effect we need to add 2 render targets, the effect and a quad renderer to our game class. (The Quad class is posted as a code snippet here and used as to render the final image).

Added these lines to the top of your game class.

RenderTarget2D leftEye;
RenderTarget2D rightEye;
Effect anaglyphEffect;
QuadRenderer quad;

//you can change this later to test different distances between the left and right eye viewpoint,
//the offset depends on the scale of your game, but small values seem to work best.
//I used 0.05 for a scene about 5x5x5 size.
float ammount = 0.05f;

And add these lines in your LoadContent method:

leftEye = new RenderTarget2D(GraphicsDevice, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height);
rightEye = new RenderTarget2D(GraphicsDevice, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height);
anaglyphEffect = Content.Load("Anaglyphs");
quad = new QuadRenderer(GraphicsDevice);

Now we need to calculate two slightly offset view-matrices, draw the scene two times using these view-matrices and then combine them using our effect. To accomplish this write the following Draw method:

protected override void Draw(GameTime gameTime)
{
    Matrix viewMatrix = camera.ViewMatrix; //use your own camere class here

    //The vector pointing to the right (1,0,0) as seen from the view matrix is stored
    //in the view matrix as (M11, M21, M31)
    Vector3 right = new Vector3(viewMatrix.M11, viewMatrix.M21, viewMatrix.M31) * amount; //ofset from the center for each eye
    Matrix viewMatrixLeft = Matrix.CreateLookAt(camera.Position - right, camera.LookAt, Vector3.Up);
    Matrix viewMatrixRight = Matrix.CreateLookAt(camera.Position + right, camera.LookAt, Vector3.Up);

    GraphicsDevice.SetRenderTarget(leftEye);
    DrawForEye(viewMatrixLeft, camera.ProjectionMatrix);

    GraphicsDevice.SetRenderTarget(rightEye);
    DrawForEye(viewMatrixRight, camera.ProjectionMatrix);

    GraphicsDevice.SetRenderTarget(null);

    anaglyphEffect.Techniques["Anaglyphs"].Passes[0].Apply();
    anaglyphEffect.Parameters["left"].SetValue(leftEye);
    anaglyphEffect.Parameters["right"].SetValue(rightEye);
    quad.DrawFullScreenQuad();

    base.Draw(gameTime);
}

And hooray! We now have anaglyphs in our game! This will result in some pretty picture (the following picture of course only make sense when you use red/cyan 3D-glasses)

Anaglyph Example, view with red/cyan glasses

When you have created some cool anaglyph images in XNA, be sure to send them in, I’ll make a small gallery here!

Tags: , , , , ,
Posted in Blog, General Coding, XNA | 5 Comments »

CodeSnippet: Quad renderer

Posted by Roy Triesscheijn on 7th May 2011

This quad renderer was already part of my conversion of Catalin Zima’s Deferred Rendering for XNA tutorial, but because I plan to use it in a tutorial I’m going to write later today here is a handy snippet for drawing a quad with texture coordinates in XNA. (You could use the SpriteBatch class for this, but as you all know the SB class tends to mess up your render state if you do not define all states correctly).

Anyway here’s the class:

    public class QuadRenderer
    {
        public QuadRenderer(GraphicsDevice device)
        {
            this.device = device;
            vertices = new VertexPositionTexture[]
            {
                new VertexPositionTexture(new Vector3(0,0,0),new Vector2(1,1)),
                new VertexPositionTexture(new Vector3(0,0,0),new Vector2(0,1)),
                new VertexPositionTexture(new Vector3(0,0,0),new Vector2(0,0)),
                new VertexPositionTexture(new Vector3(0,0,0),new Vector2(1,0))
            };

            indexBuffer = new short[] { 0, 1, 2, 2, 3, 0 };
        }

        public void Draw(Vector2 v1, Vector2 v2)
        {
            vertices[0].Position.X = v2.X;
            vertices[0].Position.Y = v1.Y;

            vertices[1].Position.X = v1.X;
            vertices[1].Position.Y = v1.Y;

            vertices[2].Position.X = v1.X;
            vertices[2].Position.Y = v2.Y;

            vertices[3].Position.X = v2.X;
            vertices[3].Position.Y = v2.Y;

            device.DrawUserIndexedPrimitives<VertexPositionTexture>(PrimitiveType.TriangleList, vertices, 0, 4, indexBuffer, 0, 2);
        }

        public void DrawFullScreenQuad()
        {
            Draw(Vector2.One * -1, Vector2.One);
        }

        #region FieldsAndProperties
        private VertexPositionTexture[] vertices = null;
        private short[] indexBuffer = null;
        private GraphicsDevice device;
        #endregion
    }

Tags: , ,
Posted in Blog, XNA | 1 Comment »

Wrapping effect files into proper classes

Posted by Roy Triesscheijn on 6th February 2011

In XNA shaders are processed into Effect objects by the content pipeline. These effect objects are not really ‘first class citizens’ because, contrarily to most C# classes, these classes have a lot of loosely-typed features. To remedy this I’m going to show you how I wrap these effect objects into their own wrapper, when we see the differences I’ll explain the pros and cons of my approach.

For this tutorial we’re going to use a part of a shader I use for deferred rendering:

float4x4 World : WORLD;
float specularIntensity = 0.8f;
texture Texture : TEXTURE;

As said, the content processor wraps this nicely into an Effect object. Now if we’d like to draw something with this effect it would probably be done something like this:

Effect effect = Content.Load<Effect>("myEffect");
//Draw:
effect.Parameters.GetParameterBySemantic("World") = Matrix.Identity;
effect.Parameters["specularIntensity"] = 0.5f;
effect.Parameters["texture"] = 56;
effect.Techniques["technique1"].Passes[0].Apply();

Given the rest of the code is correct this will compile nicely, however during runtime we will receive an exception. Because we set the effect parameter “texture” to 56, which is not a proper texture value. Due to the loose typing this error could not be detected by the compiler, so it could sneak up on us. Also it’s a bit hard to remember all the parameters an effect has, because we cant see that without opening the .fx file, I’d argue that the effect class is not a proper class as we know other classes to be in C#. And it can’t be, because it has to be compatible with so many different shaders. Therefor I push forward my approach.

For the above shader I would write the following class:

    public class MyEffect
    {
        public MyEffect(Effect effect)
        {
            worldMatrix = effect.Parameters.GetParameterBySemantic("World");
            texture = effect.Parameters.GetParameterBySemantic("Texture");
            specularIntensity = effect.Parameters["specularIntensity"];

            technique1 = effect.Techniques["Technique1"];
        }

        public void Apply()
        {
            technique1.passes[0].Apply();
        }

        #region FieldsAndProperties
        private EffectTechnique technique1;        

        private EffectParameter worldMatrix;
        public Matrix WorldMatrix { set { worldMatrix.SetValue(value); } }

        private EffectParameter texture;
        public Texture2D Texture { set { texture.SetValue(value); } }

        private EffectParameter specularIntensity;
        public Texture2D SpecularIntensity { set { specularIntensity.SetValue(value); } }
        #endregion

    }

Using this code drawing an object would look like this:

MyEffect effect = new MyEffect(Content.Load<Effect>("myEffect"));
//Draw:
effect.World = Matrix.Identity;
effect.SpecularIntensity = 0.5f;
effect.Texture = 56;
effect.Apply();

In my opinion this is a lot more readable and we now get an error while compiling that 56 does not match the type “Texture” also the new wrapper is more of an interface for the effect file. If we change one of the variable names in the effect file, we now only have to make a change at one place in our code base, even if we change the type of a parameter using some logic in the property we might still not have to change all the code. And if we really have to we will get a lot of helpful compiler warnings. We can now also find all references to a specific parameter. However the big downside is that Effect works for all effects (well you still have to remember the parameters and techniques which differ per shader), and this approach requires you to write a class per shader.

Anyway this is my approach, I’d love to know how other people handle this problem, and if you have any comments.

Update 7-2-2011:
After discussing alternative approaches (thanks Flashed!) I would like to give everybody a tip to try an extend this system. How about have a content pipeline project that automatically matches an effect file with an effect wrapper? You can use metadata in the .fx files todo this!

Tags: , , , , , ,
Posted in Blog, General Coding, XNA | 3 Comments »

XNA Farseer platform physics tutorial updated to Farseer 3

Posted by Roy Triesscheijn on 12th January 2011

Rabidlion has done an excellent update of my XNA/Farseer platform physics tutorial, which makes the code run on Farseer 3. This will bring great speed benefits, also Farseer 3 generates a lot less garbage (handy to know if you’re targeting the Xbox360).

You can find the updated version here.
(Original located here.)

I’ve also heard ‘rumours’ on his twitter feed that he’s working on another XNA/Farseer tutorial combo, so be sure to keep an eye on his website.

Update 26-02-2012, fixed links again

Tags: ,
Posted in Blog, General Coding, General Gamedesign, XNA | 6 Comments »

End of the year news

Posted by Roy Triesscheijn on 20th December 2010

So not too much big going on lately, but a couple of small news-bits might be enough to fill up this post :) .

-I’ve dropped the work on my ‘rotating tetris’ idea, I made my gf play the first two prototypes and it seemed just too confusing or too boring once it was dumbed down a bit. Oh well, I’m happy I actually made a prototype first this time.

-In search for something to keep me occupied for a longer time, I’m working on creating a deferred rendering engine for XNA4.0, I’ve find deferred rendering a lot more logical than the normal way of rendering, especially writing lighting shaders seems to be a lot more easy because the required data is a lot more structured. I sometimes wish though that HLSL was an object-oriented language, since a lot of the lighting code for different types of light is duplicate. A nice XNA4 compatible way of getting there is StichUp by Tim Jones, but I don’t think this goes far enough. Anyway for now I don’t want to get a complicated parser project in the way of writing a deferred render engine. Oh btw, to really get me started I began converting Catalin Zima’s excellent deferred rendering tutorial to XNA4.0, I ran into a few small problems (as usual) but luckily I was able to fix this with a little help of Catalin.

On some more fun news, the new XNA Developers Survival Kit (XDSK) II is out. And it includes 3 of my tutorials (MVC in games, Farseer Physics Platformer Tutorial and the Arcbal camera snippet) . Ok I kinda snail-mailed Nelson Hurst for inclusion, but I was very pleased to find out that he actually knew of my tutorials.

Well that’s all for now, I’ll be mostly working on Calculus and the Deferred Rendering Engine the rest of this vacation, oh and celebrating Christmas, new year and my birthday of course!

As usual I will sent you my seasons greetings using a lol cat:

lol cat
Seasons Greetings!

Tags: , , , , ,
Posted in Blog, General Coding, General Gamedesign, Personal, XNA | 2 Comments »

XBLIGs back in the games section

Posted by Roy Triesscheijn on 9th November 2010

As some of you might’ve heard already:

XBLIG is back in the games section on the new dashboard. I would sincerely like to thank Microsoft for realizing it’s mistake. I really didn’t think they would change it back. This offers us a lot of new and good opportunities. Because now the new changes are actually making XBLIG better instead of worse (as seen from the ‘old’ dashboard).

Anyway, try to find it and look for some cool games!

(As always a game by my making will be released ‘soon’).

Tags: , ,
Posted in Blog, XNA | No Comments »

Custom XML Serialization in C#

Posted by Roy Triesscheijn on 24th October 2010

As people who follow me on twitter might know, I was working on a reflection tutorial for C#/XNA. However I got a bit carried away with the XML Serialization.

So here’s first an XML Serialization tutorial.

In previous tutorials/code-snippets I showed how to use the intermediate serializer. But for the tutorial I wanted to serialize all the XML by hand so that it would be crystal clear for anyone following the tutorial what was going on.

Quickly I coded up the following interface:

    public interface ISerializable
    {
        /// <summary>
        /// Allows the object to serialize itself into the current xml node
        /// </summary>
        void Serialize(XmlDocument document, XmlNode parent);

        /// <summary>
        /// Allows the object to reconstruct itself from the current xml node
        /// </summary>
        void Deserialize(XmlDocument document, XmlNode self);
    }

This code should be pretty self explanatory. Remember that an XmlDocument object is also an XmlNode. So for the root object you can pass your newly constructed XmlDocument as parent node.

I quickly created 3 classes:

-Block, a simple class with texture, position scale and tinting with the ability to draw itself.
-RotatbleBlock, child class of block, with the ability to rotate itself.
-Scene, a class containing a Block[] that draws all the blocks.

Both Scene and Block, and thus RotatableBlock, implement ISerializable.

Serializing is now easy (only relevant bits here):
In our static Serializer class we do this:

        public static void Save(ISerializable root, string fileName)
        {
            //Set the culture of the saving thread to InvariantCulture so that
            //we do not get problems with different decimal seperators and the likes
            //when trying to save and load in different countries
            CultureInfo userCulture = Thread.CurrentThread.CurrentCulture;
            Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

            XmlDocument document = new XmlDocument();
            root.Serialize(document, document);
            document.Save(fileName);

            //Restore the thread culture
            Thread.CurrentThread.CurrentCulture = userCulture;
        }

Take extra care to set the culture to invariant temporarily so that we don’t get different results depending on our computer’s localization settings.

Scene is serialized this way:

        public virtual void Serialize(XmlDocument document, XmlNode parent)
        {
            XmlElement me = document.CreateElement("ReflectionTutorialEngine.Scene");
            parent.AppendChild(me);

            XmlElement blocksElement = document.CreateElement("Blocks");
            me.AppendChild(blocksElement);

            foreach (Block b in blocks)
            {
                b.Serialize(document, blocksElement);
            }
        }

As you can see the object serialized just creates a new child node in the parent node. It’s name is it’s exact full namespace name (this will be important later).

The serialization code for Block is pretty straightforward too.

        public virtual void Serialize(XmlDocument document, XmlNode parent)
        {
            XmlElement me = document.CreateElement("ReflectionTutorialEngine.Block");
            parent.AppendChild(me);

            XmlElement textureNode = document.CreateElement("Texture");
            textureNode.InnerText = texture.Tag.ToString(); //the full asset name is saved in the tag elsewhere

            XmlElement positionNode = document.CreateElement("Position");
            positionNode.InnerText = position.X + ";" + position.Y;

            XmlElement scaleNode = document.CreateElement("Scale");
            scaleNode.InnerText = scale.ToString();

            XmlElement tintingNode = document.CreateElement("Tinting");
            tintingNode.InnerText = tinting.R.ToString() + ';' + tinting.G.ToString() + ';' + tinting.B.ToString() + ';' + tinting.A.ToString();            

            me.AppendChild(textureNode);
            me.AppendChild(positionNode);
            me.AppendChild(scaleNode);
            me.AppendChild(tintingNode);
        }

Where it get’s interesting is in the serialization code of RotatableBlock:

        public override void Serialize(XmlDocument document, XmlNode parent)
        {
            XmlElement me = document.CreateElement("ReflectionTutorialEngine.RotatableBlock");
            parent.AppendChild(me);

            XmlElement rotationElement = document.CreateElement("Rotation");
            rotationElement.InnerText = rotation.ToString();

            me.AppendChild(rotationElement);
            base.Serialize(document, me);
        }

As you can see we create an element for our object as normal. We also append anything we want to remember in child nodes in the XML. The interesting part is that we pass the newly created node as a root node for the Serialize method of the base class.

This approach generates the following XML:
(We saved a Scene which had an array of blocks, which contained one normal Block and one RotatableBlock using our Serializer’s Save method).

<ReflectionTutorialEngine.Scene>
  <Blocks>
    <ReflectionTutorialEngine.Block>
      <Texture>test</Texture>
      <Position>32;32</Position>
      <Scale>1</Scale>
      <Tinting>255;255;255;255</Tinting>
    </ReflectionTutorialEngine.Block>
    <ReflectionTutorialEngine.RotatableBlock>
      <Rotation>0.7853982</Rotation>
      <ReflectionTutorialEngine.Block>
        <Texture>test</Texture>
        <Position>64;64</Position>
        <Scale>0.5</Scale>
        <Tinting>245;245;220;255</Tinting>
      </ReflectionTutorialEngine.Block>
    </ReflectionTutorialEngine.RotatableBlock>
  </Blocks>
</ReflectionTutorialEngine.Scene>

Recreating the Scene, Block and RotatableBlock from this XML file is fairly easy. Let’s first declare a Load method in our Serializer.

        public static ISerializable Load(string fileName)
        {
            CultureInfo userCulture = Thread.CurrentThread.CurrentCulture;
            Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

            XmlDocument document = new XmlDocument();
            document.Load(fileName);

            XmlNode rootNode = document.FirstChild;
            ISerializable rootObject = GetObjectFromNode(rootNode);
            rootObject.Deserialize(document, rootNode);

            Thread.CurrentThread.CurrentCulture = userCulture;

            return rootObject;
        }

        //Small helper method that creates an instance of ISerializable from a node
        public static ISerializable GetObjectFromNode(XmlNode node)
        {
            return (ISerializable)Assembly.GetExecutingAssembly().CreateInstance(node.Name);
        }

As you can see we load an XMLDocument normally. And start deserializing the first child of the document (the element in our case). I’ve added a little helper method (GetObjectFromNode) that actually does a lot of work. Via reflection it looks up the class stored in the name of the node. At first it will find “TutorialEngine.Scene” and it will thus create an instance of our Scene class.

After this we simply call Deserialize on our newly instantiated Scene object, giving it the XMlDocument and the node that represents the Scene itself.

Deserializing a Scene is now easy:

        public virtual void Deserialize(XmlDocument document, XmlNode self)
        {
            XmlElement blocksElement = self["Blocks"];

            blocks = new Block[blocksElement.ChildNodes.Count];
            for (int i = 0; i < blocks.Length; i++)
            {
                blocks[i] = (Block)Serializer.GetObjectFromNode(blocksElement.ChildNodes[i]);
                blocks[i].Deserialize(document, blocksElement.ChildNodes[i]);
            }
        }

See that we keep using the Serializer.GetObjectFromNode helper method to instantiate a block. Note that a RotatableBlock can be casted to a Block (we are using polymorphism here again). But that when deserialzing the overriden method in RotatableBlock will be used.

The deserialization code for a block is easy (and a bit dull)

        public virtual void Deserialize(XmlDocument document, XmlNode self)
        {
            try
            {
                texture = GameServices.GetService<ContentManager>().Load<Texture2D>(self["Texture"].InnerText);
                position.X = Single.Parse(self["Position"].InnerText.Split(';')[0]);
                position.Y = Single.Parse(self["Position"].InnerText.Split(';')[1]);
                scale = Single.Parse(self["Scale"].InnerText);
                tinting.R = Byte.Parse(self["Tinting"].InnerText.Split(';')[0]);
                tinting.G = Byte.Parse(self["Tinting"].InnerText.Split(';')[1]);
                tinting.B = Byte.Parse(self["Tinting"].InnerText.Split(';')[2]);
                tinting.A = Byte.Parse(self["Tinting"].InnerText.Split(';')[3]);
            }
            catch(Exception e)
            {
                throw new XmlException("Error deserializing from XML, see inner exception for details", e);
            }
        }

Note that we are using the GameServices class from a previous tutorial to get easy access to the ContentManager.

Now the interesting part is again in how we handled Inheritance in RotatableBlock, so let’s take a look at that code:

        public override void Deserialize(XmlDocument document, XmlNode self)
        {
            try
            {
                rotation = Single.Parse(self["Rotation"].InnerText);
                base.Deserialize(document, self["ReflectionTutorialEngine.Block"]);
            }
            catch (Exception e)
            {
                throw new XmlException("Error deserializing from XML, see inner exception for details", e);
            }
        }

As you can see we first set the rotation variable with the data saved in our XMLNode. However the special thing is that we now just deserialize the rest of our RotatableBlock data by calling the base.Deserialize method on the element inside our element. This way we don’t have to duplicate any code.

As you can see this is a pretty neat and clean way of writing your own XML Serialization code. It will save you a lot of work, and a lot of errors compared to writing the same boring serialization code for each object. If you have problems understanding inheritance and polymorphism I suggest that you quickly brush up on those techniques as they are crazy powerful and a must for every developer that works with an object oriented language as C#.

Be aware that there are multiple ways to automatically serialize your data, like the previously mentioned IntermediateSerializer, or using Xna.BinaryWriter.

I believe that the above code is as Xbox360 compatible as the other ways, and the nice thing is, is that it will also work when not using XNA at all :) .

Anyway, I hope you liked this. Stay tuned for the reflection tutorial for which I wrote this (yeah I did get carried away).

Tags: , , , , , ,
Posted in Blog, General Coding, General Gamedesign, XNA | 2 Comments »

Custom style-sheet to fix the XNA forum’s whiteness

Posted by Roy Triesscheijn on 12th October 2010

As many of you know, the new XNA forum is a bit white. To counter this, I’ve been looking for a stylesheet that makes everything a bit less white, so that we can actually read the forums without having our eyes burst :) . On the bright side (:P) I’ve found such a style sheet quickly. It was pre-installed with Opera (my favourite browser). If you select the style sheet: C:\Program Files (x86)\Opera\styles\user\contrastwb.css by right clicking the forums and selecting “edit site preferences” -> display and browsing for it in the “style sheet” section. You get quite a different XNA forum: For people who don’t have Opera but who do have a browser that allows you to set custom style sheets here it is: (© Opera)

@charset "utf-8";
/*	Name: 1490680844
	High contrast (W/B)
	Copyright 2009 Opera Software */
* {
	color: white !important;
	background: black !important;
}
input, textarea, select {
	color: black !important;
	background: white !important;
}
button, input[type="file"], input[type="submit"], input[type="button"], input[type="reset"] {
	color: black !important;
	background: silver !important;
}
a[href] {text-decoration: underline !important;}
a[href]:hover, a[href]:hover * {
	color: black !important;
	background: white !important;
}
a[href] img {border: thin solid white !important;}
@media print {
	* {
		color: black !important;
		background: white !important;
	}
}

Tags: , , , , ,
Posted in Blog, XNA | No Comments »

XNA: Proxyclasses to ‘Serialize’ assets using the IntermediateSerializer

Posted by Roy Triesscheijn on 28th September 2010

As some of you’ve might seen, I’ve been breaking my head over the following problem for the past few days:

How do I serialize the class like the following without creating a special ‘intermediate’ struct for each and ever classes

public class MyData
    {
        [ContentSerializer(SharedResource = true)]
        public Texture2D myTexture;
        public int myInt;
        public string[] myLines;
        public MyData() { } // for deserialization
        public MyData(int myInt, Texture2DProxy myTexture, string[] myLines)
        {
            this.myInt = myInt;
            this.myTexture = myTexture;
            this.myLines = myLines;
        }
    }

Even though I’ve marked the Texture2D as a shared resource, I still can’t serialize it using the IntermediateSerializer because a Texture2D always has a reference to a GraphicsDevice object, and the IS can’t serialize that.

Fortunately some helpfull people in #XNA on Efnet (ecosky and flashed, that’s you guys!) told me about proxyclasses, first I was confused and thought they wanted me to write a proxy for every class in my project, but soon they helped me understand that I should write a proxy class for Texture2D. I just had to write a proxy class that can be serialized and that will store the path to texture, so that it can reload itself when deserialized.

I quickly came up with the following class, very simple but it will suffice for now:

public class Texture2DProxy
    {
        public Texture2DProxy(string path)
        {
            LoadTexture(path);
        }

        public Texture2DProxy() { }

        private void LoadTexture(string path)
        {
            ContentManager content = GameServices.GetService<ContentManager>(); //My own class, see my code snippet, you can also reference a static CM here.
            texture = content.Load<Texture2D>(path);
            this.path = path;
        }

        [ContentSerializerIgnore()] //make this is not serialized
        private Texture2D texture;

        [ContentSerializerIgnore()]
        public Texture2D Texture
        {
            get
            {
                if (texture == null)
                {
                    LoadTexture(path);
                }
                return texture;
            }
        }

        [ContentSerializer()] //make sure this is, even-though it's a private field.
        private string path;
    }

Now we just need to replace Texture2D with Texture2DProxy everywhere, and update some code. In the end we can now serialize and deserialize the MyData class like this:

public void DoSerialize(MyData myData)
        {
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            using (XmlWriter writer = XmlWriter.Create("example.xml", settings))
            {
                IntermediateSerializer.Serialize(writer, myData, null);
            }
        }

        public MyData DoLoad()
        {
            MyData tmp;
            XmlReaderSettings settings = new XmlReaderSettings();
            using(XmlReader reader = XmlReader.Create("example.xml", settings))
            {
                tmp = IntermediateSerializer.Deserialize<MyData>(reader, null);
            }

            return tmp;
        }

Btw, serializing like this will generate the following XML file:

<?xml version="1.0" encoding="utf-8"?>
<XnaContent>
  <Asset Type="XNASerialization.MyData">
    <myTexture>#Resource1</myTexture>
    <myInt>42</myInt>
    <myLines>
      <Item>Two households, both alike in dignity,</Item>
      <Item>In fair Verona, where we lay our scene,</Item>
      <Item>From ancient grudge break to new mutiny,</Item>
      <Item>Where civil blood makes civil hands unclean.</Item>
    </myLines>
  </Asset>
  <Resources>
    <Resource ID="#Resource1" Type="XNASerialization.Texture2DProxy">
      <path>latern</path>
    </Resource>
  </Resources>
</XnaContent>

With this problem out of the way, I can now finally start working on a way to save and restore levels in Hollandia. Oh btw, you can ofcourse do the same trick with SoundEffects and Models or anything else for that matter.

Tags: , , , , , ,
Posted in Blog, General Coding, General Gamedesign, Hollandia, Tips, XNA | 3 Comments »