4

Say I have a few base classes:

  • HasPosition supplies a 2D location, and methods to "move".
  • IsDisplayable defines how a class will be displayed in a given graphics library (say, curses), and methods to change its representation.
  • HasHealth supplies a health value and methods hurt and heal.

If I multiply-inherit all 3 into a single class, Entity, I'll have a class that can be displayed, moved, and hurt (a starting point for a game entity).

This could be added to and mixed to yield any number of classes.

Is there anything wrong with this approach? Is it at all typical to have "top level" classes that are more or less made up of several other base classes?

I'm trying to create reusable set-up to use to create games using Pdcurses, and wondered if this was a good way to set up my classes.

  • 4
    You may find some interest in Why should I prefer composition over inheritance? where an alternative is discussed. – Kelly Thomas Apr 16 '15 at 4:04
  • As far as initial prototyping goes, OOP is very easy to prototype, and multiple-inheritance can save a lot of boilerplates or up-front system design (by postponing the separation of concerns in code, instead relying on your mental efforts for the same). Other designs start to prevail as you scale up your design, e.g. getting it to handle very large number of objects, running very fast or supporting many users, or to extend the game system in novel ways at runtime without code changes, etc. So, the question may depend on which phases your project is in, and what experiences you have on each. – rwong Apr 16 '15 at 5:29
  • You're on the right path in your comment to grey's answer. I also wanted to point you to the gamedev stack exchange - they might have boilerplate architectures in mind that you can use. – Shaz Apr 16 '15 at 14:22
  • @Ryan Thank you. I'll make sure I have a clue before I venture into more specific domains like the game-dev SE. – Carcigenicate Apr 16 '15 at 14:47
  • And anyone know why I received a downvote? I thought this was fairly well asked. – Carcigenicate Apr 16 '15 at 15:11
3

Is there anything wrong with this approach? Is it at all typical to have "top level" classes that are more or less made up of several other base classes?

Yes, and yes.

Historically, it has been common practice among game engine developers to build their game entities in exactly the way you describe. I have, in fact, several well-regarded books that describe an inheritance model for game entities.

However, in the last couple decades, developers observed that inheritance is inherently limiting:

  • Modifying the game logic to add new features requires modifying the game engine.
  • Entity relationships must be hard-coded.
  • Entity data is, by necessity, spread across large areas of memory, incurring large performance penalties for tight per-system update loops. (For example, while doing physics on sets of objects.)

Instead, what has come into vogue among game developers (and for good reason) is data-driven entity systems.

In an entity-component system, there are several performance and extensibility advantages:

  • Modifying game logic can be done trivially by attaching a new component to an entity.
  • Entity components can be allocated in batches, to keep similar data close together; this allows, for example, a physics system to quickly perform its calculations on data that literally streams into the CPU's cache, with great performance benefits.
  • Entity relationships can be defined at run-time, so that entities can be constructed entirely external to the engine, in a scripting engine, or even over the network.
  • Faster turnaround on new features--new components and component systems touch fewer parts of your codebase, requiring less work in the long run.

Data-driven design like this, and entity component systems in general are a frequent topic over on gamedev.stackexchange.com.

  • Thank you. I've heard the buzz-word "data-driven" before but never looked it up. Maybe it's time. – Carcigenicate Apr 16 '15 at 13:23
  • From the sites I could find that actually attempt to address what COP is, it seems to be basically like what I wrote in my question, but uses composition instead of inheritance. So then my question becomes, if I switch it over to composition, and have an Entity class that contains an instance of a Position, Health, and Display, is that better? Now unfortunately, I need to write all the "layer-bridging" code though (to move an Entity, I basically have to route the move call to its Position "component". – Carcigenicate Apr 16 '15 at 13:50
3

Let me provide a different, yet typical, answer: it depends.

A lot of people (me included) have troubles with inheritance hierarchies such as the ones @greyfade mentioned in the other answer. The clean code mantra "prefer composition over inheritance" stems from exactly that.

However, by understanding the problems that are at the root of inheritance hierarchies you can still get the best of both worlds. Keep in mind though, that this is heavily dependent on your language and your self-discipline.

What you have described is something that simply was not possible in a language like Java (prior to Java 8, which got default interfaces now), but readily accepted in C++ before and more modern languages like C# or Scala. In order to save themselves the tedious discussions originating from the above-mentioned troubles though, they chose to call these "mixins" or "traits" (as opposed to "multiple" "inheritance" - two words that are readily attackable by everyone with a basic CS degree). Yet in essence, your description sounds just like you're doing that.

What's important in a trait-based approach, just as well as in one based on composition (instead of inheritance), is to focus on two primary advantages:

  1. You want to be able to reuse one of these "things" without having to bother about the others

  2. and want to be able to change or replace one of these, again without having to care too much about the others.

Clearly, when you have a full hierarchy of things in a large tree, it is near to impossible to get these two advantages for an implementation class that sits somewhere in the middle of that tree. Nevertheless, when you work with traits/mixins, or essentially do the same thing via self-discipline in C++ in that you do inherit multiple times, but not form a hierarchy that has a depth greater than a single inheritance step, then you have technically used inheritance, yet you get to keep all those advantages.

You can reuse each of the individual parts independently, or even exchange them with reasonably little work. Yet this system does not save you from potentially creating intangible class hierarchies again (but then again, neither does a hammer save you from hitting your head with it).

Disclaimer; With regards to entity systems, I am personally not convinced of their superiority over traits. Both are way better than creating a big inheritance hierarchy though. Also I'm not in the gaming industry, so other effects (like the mentioned fast memory accesses) may also be important enough to your use case to justify choosing one way over the other. As usual, there is no silver bullet (unless you create one in your game) and everything has its pros and cons. Just make sure you understand the downsides of whichever way you choose.

In response to the add-on comment question(s):

It's not like the different approaches differ by being suitable or not for a simple game. I don't believe you have scalability issues with either. Traits/Mixins are quite successfully being used in rather large systems and scale well, especially because they are so nicely composable. No idea how scalability came up, but it's not really an issue for either approach here as far as I can tell.

Addressing your comment, as far as I understand it data-driven doesn't mean you have a standard composition via an attribute in your class. So your Entity class doesn't directly refer to a Position class, because that would again result in higher coupling than intended. To add a "component" to an entity you would still have to go into that class. As far as I can tell, and please be aware I'm no expert on that, the idea is to decouple your Entity from having to know the concrete "component" thing at all, but instead rely on some intermediate representation. A very simplified example may be that your entity is a key-value store and your Health component results in a "health" -> 10 entry into that store. This way, the outside world can add components to the entity, without the entity itself having to know anything about these components.

I'm not sure if I understand the gaming gurus idea correctly though (corrections from someone who knows better are always welcome), but I am under the impression that with this approach you sacrifice a lot of compile-time safety and reasoning abilities as the trade-off to gain very low coupling (hence the good scripting options with Lua and such) and potentially faster implementation possibilities (by memory alignments of this component data to optimize memory/cache accesses). Assuming that is correct, I could still not claim one way to be the right one. We all have our preferences and outside requirements that should be satisfied as best as possible.

  • So, in essence, a system like this is OK for a simple game, provided every base class is completely independent? The problems begin when you start to scale? – Carcigenicate Apr 16 '15 at 13:21
  • If you could give your opinion of my last comment on Grey's answer, I'd appreciate it. I think I'm getting the general idea. – Carcigenicate Apr 16 '15 at 13:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.