XNA: Creating a Game Framework

Hi all,

After a long time, I’m back! I’m also back to Brazil, for good, and it took me a while to settle down and start writing again.

This time I won’t talk about any fancy graphics technique or rendering optimizations. Instead, I will talk about an implementation of a game framework to be used on top of the rendering system I’m developing (and available for download on this blog), and also some tips about how to save/load your levels created with this framework. Ah, the source code is here, use it at your own risk!

Component Based System

I’ve worked with two different game architectures in my previous jobs: an inheritance-oriented one, and a component based one.

In the inheritance-oriented one, when you create a new object class, you pick up a starting class (that was inherited from the base game object class at some point), and add/override/implement relevant methods. In this architecture, sometimes you see a big inheritance tree like “Game object->physics object->render object->flying object->ship object->supership object” and so on. Ah, you can use also multiple-inheritance in some languages, that makes things more complicated and harder to maintain (in my humble opinion).

In the component-based system, you have smaller classes that are responsible for simpler tasks, like only rendering or playing sounds (named components), and you attach them to a container (called GameObject). In the example above, you could have a GameObject with a render component, a physics component and a ship component to achieve the same goal.

In both cases you can have a hierarchy of Game Objects (aka scene graph), so maybe your Render Object could be a children of the Physics Object, or whatever. In my experience, working with a component-based system proved to be easier to understand, to develop, to maintain and to extend, thus I’ve chose it for my game framework. The Unity3D game engine is a good choice to see it in action.

GameObject and BaseComponent

The two core classes of the game framework are the Game Object and the Base Component: the game object can have multiple components, children and has a transform plus some basic events. The transform is propagated to its children and to all its components. The base component is where the magic happens: the base class itself doesn’t do anything special, but here are some examples of its descendants:

Render Component: is responsible for rendering a mesh/model. The mesh itself is added/removed from an independent “render world”, so we don’t need to run through the whole scene graph looking for render components during the drawing step. When it receives a “transform changed” event, it signals the render world that it’s mesh has been touched, so the render world will render it properly in the next frame

Camera Component: it uses the Game Object’s transform plus some specific members (FovY, aspect ratio, near and far planes, viewport, etc) to define how the render world will be drawn.

Light Component: it also uses the Game Object’s transform plus some specific members (light type, radius, color, etc). It’s added to the render world, so we can query quickly what lights touch a given volume.

The base component has some “Update()” methods, that may be implemented in the sub classes. The “Update()” method is called every frame for each component that extends it (we keep a list of all the components that really need to be updated). Sometimes we need an update at a fixed rate, or just once per-frame, so what I did is was to create two different updates. I added also a “PreRender” method, that is called before the rendering so you can generate the mesh with the current camera, etc.

Here is an example of a torch, in my framework: the “torch” GO (game object for short) has only a mesh component (the burning wood) and has a child, “fire” (selected in the inspector). This GO has two components: a particle emitter and a light component. This extra GO was created because I needed an offset from the pivot of the torch to the burning tip.

There is an infinite number of components that can be implemented in this architecture, without deep inheritance trees or thousands of lines of code. In the source code provided, you can find the three examples above and a particle emitter component too. A good starting point for you to extend it is to create a Physics Component. I did two different physics components in my “official” XNA engine, using JigLibX and Box2D, and they worked quite well.

Accessing Components

Sometimes, a component may need to interact with another component. Let me say you want your torch’s light to flicker. You could either inherit your LightComponent class and create a LightThatFlickersComponent, or create a component LightModulatorComponent, that inherits the BaseComponent. It has some parameters like light minimum/maximum radius, color and intensity, along with modulation type (ie sine, random, etc). When the component starts, it asks for its GO for all the light components attached to it, and then updates all the lights accordingly. There are some different methods in the GO class to query the components by type, you can search for a single component in the GO itself, in the hierarchy starting on this GO, search for a list of all the occurrence of this component in the tree, etc.

Saving and loading

One important feature of any game framework is to save and load a level/game state/something. Creating all the levels in code may not be an option if you work with level designers or your game doesn’t fit in the procedurally-generated-content genre. Shawn Hargreaves has an excellent post about how to use the XNA/C# serializer, so I won’t write it here all over again. I will note some points I think that are important and weren’t too obvious when I faced them. The serializer by default saves all the public properties, so you may face some issues like I did:

[ContentSerializer(Optional=true)] : when you add new properties to a class, the XML loader will cry a river saying that it didn’t find that property in the XML. Add this attribute to allow the game to load without that.

[ContentSerializer(Ignore=true)]: use this if you don’t want a given member to be saved, like the “GlobalTransform” in the BaseComponent, that is just an facade to the GO global transform

[Browsable(false)]: at some point you will create an editor to your game, and a property grid is a good choice to use for inspecting properties. Use this attribute if you don’t want a property to be shown on the property grid (like an internal GUID of the GO)

[ContentSerializer(SharedResource=true)]: if a component needs to store a reference to a GO or another component, use this attribute to avoid the reference to be serialized as a property inside the component. This way, it will be stored as a simple reference to an object that was already serialized

[ContentSerializer]: forces a member to be serialized (ie you don’t need to create a public access to it)

An important class that is missing so far is the SharedResourceList. It’s a list that serializes only the references to the elements, and it’s used by the GameObject class to store its children.

I created a class named GameWorld, that is responsible for managing the GO tree. Actually it has a single GO – the root, some lists of updatable components, an instance of the render world and some helper methods. You load the level in the same way you load a texture or a mesh, like

GameObject object = Content.Load(“levels/jcoluna.xml”)

With the loaded root ready, you send it to the game world, so it can call all the initialize methods and prepare the scene graph to update and render. Take a look at the code and ask if you have any doubts, it’s not rocket science.

One last tip: keep the level files and the other assets (textures, meshes) in different projects, and do not reference the game processor where it’s not needed. If you do this, every time you change a class in the game framework, all the textures and meshes will be reimported (this is not done in this example, sorry).

I would like to thank Rudi Bravo for his help during the development of my framework, he did a good job at the dirty serialization stuffs and the Box2D integration.

That is it, keep safe, healthy, happy and donating!

-J.Coluna

About jcoluna

Game developer and musician
This entry was posted in XNA and tagged , , , . Bookmark the permalink.

10 Responses to XNA: Creating a Game Framework

  1. nobley says:

    good job man😀

    i’ve also implemented component based-system pattern to my game engine. i think this pattern easier to managed.😀
    after i see your source code, i find some differences. for example, i prefer to make transfrom to be a component, call it “Transform”. Every game object should have one transform component (like unity3d). so it is easier to share transform to 2D component, although transform component is more intended for 3D component.
    beside the point. I also prefer to make a custom serializer. so I am more free to make insert some non-serialize objects like graphics device and engine object (like your Game Context).

    in my render system, i adapted from your light pree pass renderer. thanks man😀
    currently I’m developing a game editor for visual studio addin. so far its development has reached 95%, and need finishing touch before published it. this editor support to make 2d and 3d level editor.

    i really like your assistance,😀

    • jcoluna says:

      It’s really nice to hear that you are using some of the LPP code into your engine!
      There are many different ways to implement a game framework, and I’m pretty sure the way you did it fits your requirements – that’s what really matters =)
      See ya!
      J.Coluna

  2. Tiba says:

    Hey mate just want to say i love your work it has helped me so much
    im using it as my render system….. your name is in the credits🙂.
    I have added for post prossesing ToneMapping, HDR, DoF, Bloom,
    and for out door rendering Atmospheric Scattering, Dynamic Clouds, Night and Day Cycle.

    Im moving a long very well i have my editor up and running and all is well,
    but im stuck on 3 things God rays, terrain painting and terrain editing are there any tips for these 3 things you can give or any code to help along the way?

  3. Looks good. I’ve always preferred the component based approach, as although both are useful I find composition > inheritance. This avoids that classical ‘class explosion’ that can otherwise occur with overuse of inheritance. I enjoy the style in which your articles are written🙂

  4. Tiba says:

    Hey mate just wanted to give you an update and a pic of my editor,
    It just dawned on me that i can use any shader i want in the ReconstructShading pass
    so what that means to me is i now have a water and glass shader that i can add to any mesh and have it go throu the full LPP pipeline and be trancelucent with shadows and lighting(still need to change the glass\water shader to uses the lighting and stuff).

    This has opened a lot of doors as i have it set up so in 3ds max i had or to the name any mesh part and the renderer will use the right shader when it renders it in game.

    In the screen shot you can see 3 mesh’s with the 3 shaders on them(center is LPP ReconstructShading, left is water and right is glass) , also you can see some clouds and the sky and a few other things…… all thanks to your render pipeline🙂 ill me donating in a few weeks

    http://imageshack.us/photo/my-images/140/editorpic.jpg/

    Thank you so much for the god rays🙂 in advance🙂 its one of the last things i need to make my out door setting look sweet.

    (if any wants to see the code im happy to post it)

  5. Maciej says:

    First of all, excellent articles. You’ve managed to show very tricky concepts in quite easy way.

    I’ve managed to easily follow all your tips from previous posts, but got quite lost at this stage.

    I’m generating a dynamic skybox, which updates every frame and uses its own model and effect files. Until now, it was pretty straight forward, but with the new ‘generalized’ things got a bit more confusing. My guess would be to create a new SkyboxComponent and use the PreRender function to calculate all my displacements and set shader options. And this is the part I’m not sure about.
    How would you go about setting mesh effect variables from a custom component?

    Or am I approaching this from a completely wrong way?

    Thanks!

  6. This particular posting, “XNA: Creating a Game Framework | J.
    Coluna” demonstrates the fact that you truly know just
    what u are talking about! I 100 % agree with your post. Many thanks -Angelo

  7. Pingback: Depth buffer with XNA: did I miss something or… | Infinite Productions blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s