What are game objects? Simply put, they are the entities that make up your game. A character in a game, a tree which is a part of the game landscape, buildings, walls, sprites, menus, the HUD, platforms, NPCs and mostly everything that you see within a game are all examples of game objects. It would be fair to say that everything and anything you observe within a game is a, or is a part of a game object. But what about things that you can’t see? What about sound sources within a game that produce sound? The sound coming off a running stream, or off a exploding mine, or off a moving car — can they also be modeled as game objects? Yes indeed they can be. In fact there are also game objects that you can’t see or hear — for example, a trigger that makes a land-mine go off, or a proximity-switch that opens a door when your character stand near it — are are all examples of game objects. If we look at our previous examples, the sprites that we used for our simulations could be considered as game objects. In simple terms a game object is an entity within a game that takes part, directly or indirectly, in the process of the game simulation. A game object could (but not always) have behavior and properties modeled into it to fulfill a specific purpose within the game world. Game objects can and do directly interact and participate in the gameplay. An example of interactive game objects could be enemy NPCs that attack your character while he/she is completing a quest. Such objects directly interact with the gameplay. Other game objects may not interact at all with the gameplay, but are there to serve some other purpose. Game objects like trees, shrubs, grass that litter a vast game landscape may not be direct participants in a game, but are there to serve a different purpose — that of creating a believable landscape within a game.
Having understood what game objects are, let’s see how we can add game objects to our framework. At a very basic level, most game engines have some sort of a top level GameObject class. They may be called different things — “GameEntity”, “Actors”, “CoreObject” or some other name you could think of, but mostly they serve the same purpose. A GameObject class or interface is usually an abstraction for the most basic object related functions. There are many ways you could model such game objects. The simplest that one can think of is obviously a class design based on inheritance. In an inheritance based design, you have an interface or a base class called GameObject and all your specialized game objects classes derive from this base class/interface, each adding it’s own specialized functionality. This is the traditional way of designing a game object class — and many game engines still use this method. However this design has a several issues. A game can have tens if not hundreds of types of classes, and there are situations when an inheritance based approach quickly becomes complicated and unmanageable. There are often situations where the characteristics of two distinctly separate game objects overlap even though they are hierarchically dissimilar. Considerer two GameObjects, a Bird and a SpaceShip — both can fly, but based on your design the two could be modeled differently. At the very least you may have to duplicate parts of the flying code for both objects and maybe other pieces of code that are directly or indirectly related to flying.
There are also instances where objects can’t be correctly classified via an inheritance based approach because many game objects just can’t be classified in a rigid inheritance hierarchy. Consider a situation where an object can be classified as two different types of objects — for example, you make all the Buildings in your game as static indestructible objects. You do this by creating a class called Building which derives from the class IndestructibleObject. However later in your game you may want one of the building to blow up. To solve this you would either have to make changes to your Building class so that it has the ability to destruct and blow up — or you will have to create a new class called DestructibleBuilding. There are problems with both scenarios. Making the Building class destructible will mean all your buildings will be destructible — which may not be what you wanted in the first place. The second and the more plausible option is to create a derived class called DestructibleBuilding and derive it from a DestructibleObject to make it destructible. However even with this approach you will find that there are problems. A destructible building may be 99% similar to all other buildings, but since you made a new class and derived it from a DestructibleObject, you will have to duplicate most of the code used in the original Building class. Duplicating code is just not the right way to go — is it? Well, some would argue that you could use multiple inheritance — derive the DestructibleBuilding from both the Building and DestructibleObject classes. Well, the original Building class is a IndestructibleObject and since an inheritance relationship is a “is a” relationship, a DestructibleBuilding can’t be both a DestructibleObject and an IndestructibleObject — that’s just plain absurd, not to mention that it may also cause a “diamond of death” in your hierarchy. If you are making such choices in your design, it’s time to pause and introspect, because this is a classic case of “shooting yourself in the foot”.
As you can see inheritance makes object design rigid. There are situations when this is desired, however in the case of our game objects this might not be the ideal solution. So what other alternatives do we have besides an obvious inheritance approach? The other way of approaching the game object problem is via composition. Instead of having separate classes for each kind of game object, we have a single GameObject class and build our game objects by giving them properties and defining behavior. This will allow us more flexibility since object properties and behaviors are decoupled from the class implementation. Taking the previous example, any Building in the game just becomes an instance of class GameObject instead of a separate class derived from GameObject. Since we are not modeling behaviors or properties via class inheritance, there will be no class called DestructibleObject, since Destructible is now a property and needs to be modeled separately. Properties have no direct dependency with the GameObject class. A GameObject is associated with property class via a more loose “has a” relationship. For a Building that we intend to make destructible we simply assign it a property called Destructible. In fact, once created the Destructible property can be assigned to any game object. So is the case with any other property that we create. Fig. 10.2 shows this more clearly.
Properties by themselves only define a GameObject. They are used to create an object, but they by themselves don’t do anything. In our example, the Destructible property doesn’t make the Building explode. It only tells anyone who is interested — “yes, this Building can explode”. We will obviously need to have something that will make the Building explode when it sees the Destructible property — and when the time is right, for example — a missile hitting the building. That’s were behaviors and conditions come in. We will talk about behavior and conditions in more detail in a separate chapter where we will see how to model behaviors and combine them to give us the desired behavior for an object. For now we will focus on GameObject creation. It’s easier to just think of an object as a instance of a GameObject with a collection of Properties. This may appear confusing at first, but later you will see the benefits of this approach.
We covered quite a bit of theory in this chapter, but it was necessary in light of things to come. We will end this chapter here and look at game object creation in the next.