Game Development Reference
In-Depth Information
Multiple Inheritance Is Evil
If at all possible, try to never use multiple inheritance unless every base class
you
re deriving from has nothing but pure virtual functions. You can have
one exception to this and inherit from a single base class with data
members, but every other base class should only contain pure virtual
functions. This is so important that some languages,
'
like Java, actually
enforce it.
Clearly, this is not an option. Another possibility is to shuffle around the hierarchy
and make Pickup inherit from AnimatingActor . This would solve the problem,
but it means that all pickups have to carry around the weight of the animation sys-
tem, which is most likely nontrivial. What about if you want to have a ghost charac-
ter that ignores physics? They still need to animate and render, but you don
'
t want
the physics system to even have to know about them.
These kinds of problems give rise to the dreaded blob class. You keep shuffling
around functionality until it all ends up living in one or two gigantic classes. Each
change you make is like trying to untangle a web. You ' ll be lucky if you can make
any of these changes without breaking half of the actors in the game. Obviously,
this kind of architecture is fundamentally flawed.
Component Architecture
Go back and take a look at Figure 6.1 again and notice how all of those subclasses
are really just trying to add a new feature to the actor. If you can encapsulate each of
those features into a component and compose a final object made up of those com-
ponents, you can get the same functionality as the old class hierarchy but still have
the flexibility to make changes. The Actor class becomes nothing more than a place
to store components. What ' s even better is that these components are built up at
runtime, so you can add and remove them during the course of the game. You
can
t do that with the old inheritance model!
The components have a base class that the actor maintains a reference to as well as a
subclass interface that represents the responsibility of that component. Each subclass
of that interface is an implementation of that responsibility. For example, you might
have one interface class called AiComponent , which has several different implemen-
tations for different kinds of AI. The important thing to note is that each component
interface has a unique identifier, and each actor is only allowed to have one class of a
particular responsibility. That means you could have two AiComponent subclasses,
but you could replace an existing one with a new one, allowing you to change the
actor ' s behavior at runtime.
'
 
 
Search WWH ::




Custom Search