Game Object Component System

By February 5, 2010 Blog, Featured, XNA Games 10 Comments

Last time i updated with saying that i included a Game Object Component system. I have update this system, so that it uses interfaces instead of overriding virtual methods defined inside the GOComponent base class.

Here is a class diagram of my current state of the GO’s and GOC’s.

The Manager on the Top Left is optional, that is just a helper class to add new GO’s into the game and draw/update them when it is needed.

The following image show’s an object ingame, also don’t forget to visit here once you are done reading.

This object is made of several GOC’s that are attached to one GO. The following list is an overview of the type of GOC’s that are attached to this GO.

  • GOCOnHit – Makes my GO hittable
  • GOCPhysicsObject – Attaches a Physics Body/Geom to the GO
  • GOCTexture – Makes the GO visible for the player (Texture)
  • GOCHealth – Because its hittable, it will need a Health Pool :).

These four GOC’s make up most of my environment objects for now that can be destroyed by the player. All four derive from the GOComponent base class, but only some of them are implementing the Interfaces as you can see on the class diagram. Now when the object will be Hit by another Physics object, the Physics GOC’s will process the collision handler. If the collision is valid, a message will be broadcasted among all the GOC’s and they act according to that specific message. Here is another picture if i keep hammering it with my guns, it explodes when its health reaches zero:

All those green lines and dots around my GO’s come from the Farseer Physics debug viewer. Every Game Object that has a Physics Body attached to it can be debugged this way.

I can post some code if it is needed, but this code will mostly be focused on my needs inside the game. So if you do want to see some code, just post a reply and we will make it work :).

10 Comments

  • Michele Giacalone says:

    Hi Vincent,

    Can I ask you about:
    - How GameObject manages GameModules?
    - How the message system works?

    Thanks,
    Michele

    • Vinnie says:

      Hey Michele,

      How GameObject manages GameModules?
      Basically what i have inside my game is that my gameobject doens’t rely on any of the components attached to it. The components only extend the functionality of that specific gameobject. In the class diagram you can see that i specified the two interfaces for both updating and drawing. These interfaces are the only concern for the game object. Once i tell the gameobject that a component needs to be attached to it, it will ass the component to the private lists that the game object stores. Here is a sample of the function:

      /// <summary>
      /// Adds the supplied Component to this Game Object
      /// </summary>
      /// <param name="gameObjectComponent">The game object component.</param>
      public void AddGOC(GOComponent gameObjectComponent)
      {
          // Do not accept any null references
          if (gameObjectComponent == null) return;
      
          // Add the owner to this component
          gameObjectComponent.SetOwner(this);
      
          // Check if the new component already exists. If so it will be overwritten with the new one.
          // Note: Removed for now, as some GOC's may be duplicated inside the collection. If this will be implemented,
          // exclude the items that may have the same component multiple times.
          // Note: May be implemented if needed
      
          // Only add the component to the list if it doesn't exists yet
          _collectionGOComponents.Add(gameObjectComponent);
      
          // Sort the components based on their priority
          _collectionGOComponents.Sort((g1, g2) => g1.Priority.CompareTo(g2.Priority));
      
          // Recreate the Renderable components list (this maybe can be done nicer...)
          _collectionRenderableComponents = _collectionGOComponents.FindAll(goc => typeof(IGOCRenderable).IsAssignableFrom(goc.GetType()));
      
          // Recreate the Updateable components list
          _collectionUpdateableComponents = _collectionGOComponents.FindAll(goc => typeof(IGOCUpdateable).IsAssignableFrom(goc.GetType()));
      }
      

      Now when the update is called for this specific GameObject, the components inside the collectionUpdateableComponents list will be updated. Same applies for the components that needs to be rendered.

      For me, messaging works pretty much the same way the update and draw interfaces works. A component implements the IGOCMessage interface and preforms specific tasks inside that function when a expected MessageType (enum) is used. My game object simple has the following function for this:

      /// <summary>
      /// Processes the message.
      /// </summary>
      /// <param name="message">The message.</param>
      public virtual void ProcessMessage(GOCMessageType message)
      {
          // Fetch the list of components that implements the message interface
          List<GOComponent> components = _collectionGOComponents.FindAll(
              goc => typeof(IGOCMessage).IsAssignableFrom(goc.GetType()));
      
          // If none got the message interface, do nothing
          if (components.Count == 0) return;
      
          // Else we process the message inside these interfaces
          foreach (IGOCMessage component in components)
          {
              component.ProcessMessage(message);
          }
      }

      I hope this makes things a bit clear for you. If not, say so and i will try to help you out :).

    • Michele Giacalone says:

      Yes, helpful answer :)
      Thanks again!

  • KG says:

    I have a question about your message types. If GOCMessageType is just an enum how are you passing data along with it? Im guessing something like GOCOnHit passes a MessageType.TookDamage but what about how much damage? Or is GOCMessageType a struct/class that contains some generic flags too?

    • KG says:

      Sorry I guess I should have read the previous comment a bit better. I’ve been working with a system like this for a couple months but having a component which rely on other component’s data can be frustrating in some instances. I’m strongly considering refactoring to a message system instead of allowing a component to try and pull another component from its parent object.

  • Andreas says:

    Hey Vincent and thanks for some very interesting reads about the game object component system as well as the 2d lighting articles (I haven’t been starting HLSL yet, but I’ve bookmarked those pages for future reference due to flashlight being exactly what I’m looking for). I understand if this is a bit late perhaps to be asking but I’d really like to get one thing clear in my mind, namely: How would one go around adding enemies for instance? Would I still be creating a class called Enemy which inherits GameObject but sets a couple of default components? If I understand correctly it’s the game components that make up the object (similar to what Mick wrote in this article: http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/) and not the class itself.

    I mean, a player and an enemy will have different update methods so some kind of override would become necessary but creating those classes feels a bit like taking a step away from the purpose of this system. The answer is probably something quite easy that I just haven’t thought about, I have a tendency of missing the most obvious things :)

    I’m still looking forward to the 3rd lighting article about spotlights if it’s still in the making. It’s a very interesting read indeed.

    / Andreas

    • Vinnepin says:

      Hey andreas, basically it’s exactly what he describes in your link. If can program your game entities the way he describes t in his post, you can reuse the game objects for whatever you like. It keeps the system very flexible and adding new stuf to it is a piece of cake then, rather then going through all the code again for every entity class.

      As for the post on the spotlight, i have been very busy lately and almost got no time for myself :P. For one, i got a 9 months old kid running around here, second i need to remodel some of my house that wasn’t finished yet, thirth i’m busy in the garden replacing the pond i had (dangerous for the little one…) and it was big…., forth i am working on 3 applications for the windows phone that have to be finished befone the end of june… Wel if that list doesn’t keep me busy in my spare time, i dont know what will hehe :).

      Seeing i got some spare time a.t.m. i will look into the code for the spotlight right now, but it wont be a long post :).

  • Baker says:

    How is the textur component getting the position from the physics component? And I am not sure I understand how messaging works or what it is used for if only enums are passed in. Wouldn’t the other components need access to data within other components like the texture needing the physics body position in order to draw correctly? Thanks for your help in advance. Btw I love following your work keep us posted.

    ~Baker

Leave a Reply