Roy Triesscheijn’s Weblog

My programming world

Archive for August, 2010

Hollandia progress report #1

Posted by Roy Triesscheijn on 27th August 2010

So, it’s again time to show off a bit more Hollandia here. Today I was working on the dialogue system, very basic functionality really. A dialogue consist of a series of frames. Some frames have special actions like activating a generic trigger or by showing a couple of options, instead of just text. Of course the character talked too can respond to different suggestions (this is done by associating each of the options with an index to a next frame).

As I said pretty basic and I still need to think out a smart way to highlight a couple of words without this interfering too much with all the draw code.

I thought it would be very cool if the dialogue screen doesn’t just appears and disappears instantly so using our prepared effect system (some nice abstraction around the actual effect files) I quickly cooked up a new shader added a few lines and yay, there it is.

I’ll get more into the technicalities later (make a comment if you’re interested in any specific subsystem). For now I’ll just show you this (very much in development) sneak peak of Hollandia that I uploaded today:

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

XNA: Accessing ContentManager and GraphicsDevice anywhere anytime, the GameServiceContainer

Posted by Roy Triesscheijn on 25th August 2010

A quick code snippet that I produced today and wanted to share.

Often you find yourself looking for a good path/way to give a certain component access to the ContentManager. Usually you will just plug it in the construct. However sometimes the object creating the new object doesn’t have access to this component as well. Things start to become a bit more complicated then, of course you can add it to both constructors, but things often start to clutter.

Objects like the ContentManager and the GraphicsDevice are often needed on the craziest of places in a game’s code. They can easily be shared as they are usually in a valid state throughout the runtime of your program and usually you don’t need more than one. For these kind of objects it would be easy to create a static class so that anyone can access them.

A common technique is to create a static List in which you can throw anything in. But this doesn’t enforce that there is only instance of a given type in the container (why add two GraphicsDevices?) and makes it hard to get the right component from.

Luckily XNA has the GameServiceContainer class which allows you to store elements like this:

container = GameServicesContainer();
container.AddService(typeof(GraphicsDevice), device);

There’s also GetService and RemoveService. However this casting can make a lot of lines way longer than they need to be. Also we need to make the container static and protected access to it, so let’s create a nice little class like this:

public static class GameServices
    {
        private static GameServiceContainer container;
        public static GameServiceContainer Instance {
            get
            {
                if (container == null)
                {
                    container = new GameServiceContainer();
                }
                return container;
            }
        }

        public static T GetService<T>()
        {
            return (T)Instance.GetService(typeof(T));
        }

        public static void AddService<T>(T service)
        {
            Instance.AddService(typeof(T), service);
        }

        public static void RemoveService<T>()
        {
            Instance.RemoveService(typeof(T));
        }
    }

In the Initialize method of Gam1.cs put this:

protected override void Initialize()
        {
            base.Initialize();
            GameServices.AddService<GraphicsDevice>(GraphicsDevice);
            GameServices.AddService<ContentManager>(Content);
        }

Remember that GameServices is static so you can read, add and remove from anywhere in your code like this:

GameServices.AddService<GraphicsDevice>(device);
myDevice = GameServices.GetService<GraphicsDevice>();
GameServices.RemoveService<GraphicsDevice>()

Quite a nifty way of doing this, if I may say that myself (A). However do note (as NullSoldi did on Efnet #xna) that this will increase coupling between your components as some class will start to depend on the non standard class we’ve just created while this otherwise wasn’t needed. However I personally think that the benefits greatly outweigh the small penalty on coupling.

Have fun with this snippet, let me know if you’re using it or found it useful for your own GameServices-like class.

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

Hollandia and Farseer physics

Posted by Roy Triesscheijn on 20th August 2010

The website header for Hollandia, starring Tulpje
I don’t know why I didn’t break this to everyone before. But I’ve been the lead developer of Hollandia for a few weeks already. Click the image or link to find out more :) .

For Hollandia I’m doing a rewrite of the engine. Since it’s a platformer the characters need to be able to jump onto things. So I had a choice to either write my own mini-physics-engine for this or to look for a valid alternative that I could easily plug in into the code that I had already written. Luckily I chose the last option and came across Farseer physics and I’m completely hysterical about it. After only one day of using it I’ve donated $10,- to show my support. Ok the manual pages could use a bit of work, but to aid in that I’m writing a Farseer physics platformer tutorial for the Sgt. Conker XNA Article Contest in which I will put everything that I’ve found out about Farseer so far (see it as a gentle introduction, since once you ‘get it’ Farseer is very easy).

Anyway some who follow my youtube channel might’ve seen this already, but I made a small video where you can see that I’ve implemented Farseer physics into the engine. Things are really starting to come together (Screen managers, Scene Graphs, Layered system etc… unfortunately you can’t see any of that in the video). Especially the artwork is really nice, but since I didn’t make the art work, I’ve turned it off for the below video. (I’m just showing the physics bodies).

And no, this is not the 4×4 all terrain infinite horsepower brutal Segway of doom ©. This is actually our main character walking around. (It doesn’t look so silly if you imagine a texture of a Dutch girl moving around instead of these funny boxes :) . The idea to do it this way came from this blog article by Bryan Dismas which in turn is based on this blog article by Robert Dodd

Tags: , , ,
Posted in Blog, Hollandia, XNA | 3 Comments »

XNA: Preventing starvation/underflow when moving 2D objects slower than 1 pixel per frame

Posted by Roy Triesscheijn on 12th August 2010

Another title for this article could be: “XNA: Preventing starvation/underflow when updating integers with less than 1 each frame”.

A very naive (but usually) working method for making 2D objects move in XNA is by placing the following code in the update method.

//Assume we hold position by a rectangle, since we can use that so easily in the spritebatch
myCar.Y += (int)(gravity * gameTime.ElapsedGameTime.TotalSeconds);

This will make your object fall down with ‘gravity’ pixels per second. However since rectangles use integers for positioning, and an integer can not hold information after the seperator (eg 1.5 would become 1 for an int) objects will not move when gravity is very low or updates are very frequent.

Although, I say very low, but since the updates are done 60 times per second (if you’re using fixed timesteps, else it might even be a lot higher), gameTime.ElapsedGameTime.TotalSeconds will usually be 1/60th. This means that for an object to move, it should move with at least 60 pixels per second. That means, depending on your game’s resolution, that would mean in full HD an object moveing from the top of the screen to the bottom of the screen has to do this in 18 seconds or less, else it won’t move (1080 high divided by 60), in SD this is even worse, 8 seconds (480/60).

There are two approaches here, one way is to change the way we modify integers, this is a good approach to use inside for example an object, that modifies the position of ONE other object.

//Code inside for example a gravity class
underflowFloat += gameTime.ElapsedGameTime.TotalSeconds;
myCar.Y += (int)underflowFloat;
underflowFloat -= (int)underflowFloat;

Although this approach is simple and efficient, there are two drawbacks to this approach:

  • If you have multiple objects that modify one other object, then you will have a lot of extra floats hanging around
  • An object will need one float per direction per object that it modifies. For a gravity class that might influence all your objects this is very inefficient.

A second approach would be to modify the object itself, a handy way to do this is properties.

public int X;
private float underflowX;
public float Xfloat
{
    get { return (X + underflowX); }
    set
    {
        X = (int)value;
        underflowX = (value - (int)value);
    }
}
//Same for Y

This approach is way more useful since it will make sure that all your code that is using integers won’t break, while you still have an accurate floating point based position if needed. Basically we store all the data after the seperator in our variable underflowX. If the integer values get changed, we will still return the correct values as float. If the float values are changed, the integer is updated to be as precise as possible.

Remarks

After asking for some feedback in #XNA I got a few comments  that I bundled here, please read these!
There are more options, you could store the position as a Vector2 and cast the X and Y to integers only when you need to (but you shouldn’t ever if you start from scratch). Then you can either cast to integers when drawing, or use the SpriteBatch’s overload that uses a Vector2 for position (you will see some blending/blurring if the object is not pixel-aligned). Remember that if you cast to integers, that you will lose precision when you store the values back, this may or may not be a problem (it might not even be noticeable, but if you keep casting 5.999 to 5 every frame it might become noticeable).

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

XNA XML ContentImporter

Posted by Roy Triesscheijn on 7th August 2010

Quite often you’d like to use XML files in your games. You can use the standard XNA XML Importer for this, however then you’d need to write specific class that serialize to and from the special XNA XML documents that have a <XNAContent> tree.

If you’re trying to build your levels in XML or if you’re trying to set a high volume of settings this might not be the easiest way. Easier would be to just parse a hand written XML document yourself. Luckily this is very easy to accomplish.

The naive way of doing this is by just writing a custom content importer that would look similar to this:

[ContentImporter(".xml", DisplayName = "XML Content Importer", DefaultProcessor = "None")]  //TImport was defined as System.Xml.XmlDocument a bit higher
    public class XMLContentImporter : ContentImporter<TImport>
    {
        public override TImport Import(string filename, ContentImporterContext context)
        {
            XmlDocument document = new XmlDocument();
            try
            {
                document.Load(filename);
            }
            catch (Exception e)
            {
                //Write error logger here or update the exception with more information
                throw e;
            }
            return document;
        }
    }

(Don’t forget to add a reference to your content pipeline project to the Content project inside your game’s project)

Now the following code doesn’t work and will throw an error similar to this:

Error   1   Building content threw InvalidOperationException: Cyclic reference found while serializing System.Xml.XmlDocument. You may be missing a ContentSerializerAttribute.SharedResource flag.

Now I’m not going to be holier than the pope, I actually made the same error as you can blatantly see here.

Unfortunately the error message is very unhelpful in this case, and might even throw you off completely since the error is not visual from the actual content file itself. Any XML file while give you this error.

Luckily user Saw was sitting around in #XNA on Efnet (IRC). He told me that the error comes from the fact that I’ve written no ContentWriter (and ContentReader). This means that reflection is used to serialize the XML document.

An XmlDocument has a lot of XMLNodes. An XmlNode has the member variable parent, which is an XmlNode, which has the member variable ‘parent’, which…. Well you get the idea. Probably the recursion error comes from there.

He then showed me how two write a very simple reader and writer. If we extend our content importer with these two extra classes this problem is easily solved.

[ContentTypeWriter()]
    public class CustomXmlWriter : ContentTypeWriter<XmlDocument>
    {
        protected override void Write(ContentWriter output, XmlDocument value)
        {
            value.Save(output.BaseStream);
        }

        public override string GetRuntimeReader(TargetPlatform targetPlatform)
        {
            return typeof(CustomXmlReader).AssemblyQualifiedName;
        }
    }

    public class CustomXmlReader : ContentTypeReader<XmlDocument>
    {
        protected override XmlDocument Read(ContentReader input, XmlDocument existingInstance)
        {
            if (existingInstance == null)
            {
                existingInstance = new XmlDocument();
            }
            existingInstance.Load(input.BaseStream);
            return existingInstance;
        }
    }

The custom content writer just uses the XMLDocuments built in Save function which is aware of these cycles and deals with them properly, the other method is overload to tell XNA which content reader to use for this type. The content reader again uses the simple built in Load function, nothing special here.

However now compile your project again, see the errors are gone :) .

Let’s add a simple XML file to your content project, I’ve named it hello.xml.

<?xml version="1.0" encoding="utf-8" ?>
<MyTag>Hello World!</MyTag>

Click the file in the solution explorer and set the build action to ‘Compile’ and the Content Processor to ‘XML Content Importer’ (you can change the name by changing the DisplayName attribute). Note: you might need to recompile before you can do this.

Load and display it like this:

XmlDocument xml = Content.Load<XmlDocument>(@"Tests\xmltest");
XmlNode node = xml.SelectSingleNode("//MyTag");
Console.Out.WriteLine(node.InnerText);

The expression “//MyTag” is an XPATH expression to query the XML document, you can learn more about that here.

I hope you have a lot of fun with this code, and that it makes life a little bit easier for you, either by handling XML files for you, or by being a small source on how to write custom ContentTypeWriters and readers.

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