Class Hierarchy in Games

Started by
11 comments, last by Side Winder 14 years, 6 months ago
Hey, Usually I do the whole GameObject <- Enemy <- Monster1 or whatever, but I've recently just read this article on Data Driven Design: http://ai.eecs.umich.edu/soar/Classes/494/talks/Schumaker.pdf And now I'm slightly confused... I was thinking of trying this data driven design method, it seems quite good. Correct me if I'm wrong though please lol. The guy also talks about containment rather than inheritance because sometimes objects won't fit in an inheritance hierarchy. Instead he suggests you split up the hierarchical levels into things like Behaviour (powerup, enemy, player etc), model (animating, non-animating) and movement (fly, ground, swim etc). The base GameObject class would then contain instances of these three classes so:

class GameObject
{
    Model model;
    Behaviour behaviour;
    Movement movement;
}
So how would this work exactly? I'm still a little confused by what he was talking about. What methods would I use in Enemy and Monster1 to make this work? And how would I instantiate all the different enemies in run-time? What about the Player? Obviously the Player class won't work in quite the same way as NPCs...
Advertisement
Quote:Original post by Side Winder
Hey,

Usually I do the whole GameObject <- Enemy <- Monster1 or whatever,


Ugh.

Quote:
So how would this work exactly? I'm still a little confused by what he was talking about. What methods would I use in Enemy and Monster1 to make this work?


That is the point, there are no Enemy or Monster classes. The methods are defined in the Behavior, which can then be applied to a number of objects.

Quote:
And how would I instantiate all the different enemies in run-time? What about the Player? Obviously the Player class won't work in quite the same way as NPCs...


By taking a variety of models/behaviors/etc and instantiating them. Then assembling the bits into an instantiated GameObject (or whatever class you're compositing).

In general though, it seems like you should focus more on composition to get that concept before focusing on the data-driven approach to solutions.

In your specific example, I think the "Enemy" level of inheritance would move to the "behavior" component, as Monster1 would just use an enemy-like behavior. It's the whole "is-a vs. has-a" concept. Inheritance defines when an object "is a" variation or derivation of another object. A monster is an enemy which is a gameobject. So the Monster1 would inherit all the methods of the enemy type, which would have inherited all the GameObject methods.

Composition works from the other direction. Every GameObject has a model, behavior, and movement (type). Therefore each gameobject's method list is composed of the methods of it's parts. (edit: explained more below)

GameObject::Gameobject(Model model, Behaviour behaviour, Movement movement){mModel = model;mBehaviour = behaviour;mMovement = movement;}//then, laterGameObject Monster1(animating, enemy, ground);


Now you've defined an object with an animated model type, an enemy behavior, and ground movement.

The object class would probably then define its methods in reference to the components, i.e.
void GameObject::Move(){mMovement.move();}

As a very simplified example.

Hazard Pay :: FPS/RTS in SharpDX (gathering dust, retained for... historical purposes)
DeviantArt :: Because right-brain needs love too (also pretty neglected these days)

Quote:Original post by Side Winder
http://ai.eecs.umich.edu/soar/Classes/494/talks/Schumaker.pdf


That's a really great presentation, one of the best (and few!) I've seen on this topic. It also inspired me to try creating a Pac-Man clone. [smile]

Thanks for the link.
Riverman Media has an article about this topic:

http://www.rivermanmedia.com/programming/20-object-oriented-game-programming-the-behavior-system

Check out Super Play, the SNES inspired Game Engine: http://www.superplay.info

I appreciate the help guys. I've located another article on programming Component based. Here's the link for anyone who's interested:

http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/
Quote:Original post by Side Winder
I appreciate the help guys. I've located another article on programming Component based. Here's the link for anyone who's interested:

http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/


There's a difference between favoring composition over inheritance and component based programming. That article itself is probably the source of innumerable over-engineered pipedreams in recent memory.
/cry

OK... On your first post you said "ugh" for the inheritance way I used to do things. Could you explain a better route? I'm getting a bit frustrated with the overwhelming amount of information.
The core misuse of inheritance is using it to encode information. In most popular languages, accessing the type of an object is not easy/quick/good.

By going Object -> Enemy -> Monster1, you run into the common problem of 'what are you?'. How do you determine what that Enemy is? You end up doing a bunch of type inspection operations which are sucky. If you just had that as member data, it's very simple.

That goes for a lot of other inheritance. Inheriting everything from GameObject just so you can put everything into a container isn't helpful. What do all objects have in common? Next to nothing. Best case, you get an interface for serialization. Since we're in For Beginners, that's probably not going to be a concern.

Anytime you put information into the act of inheritance (instead of just letting inheritance change the functions it overrides) it makes the program worse. A code smell as it were.
OK, yes, I understand the arguments against Inheritance in this setting. I also understand that going Component-based would be a lot better. I am, however, having trouble with implementing a solution. You're right, I don't want anything fancy and over the top because I'm not creating a large game with hundreds of entities.

Let's say I'm creating an Asteroids clone (I'm not, but it's similar) and I want to have three different sized Asteroids: large, medium, and small. They'll have different models, different characteristics, different explosions, different scores etc. Now, if I were to implement this as Component-based, what would I do?

Would I...

class Entity{    Behaviour mBehaviour;    Model mModel;    Movement mMovement;}


Along with a Behaviour class that has Player, Enemy, Powerup etc classes derived from it.

But surely Enemy would have Asteroid derived from it as well? And then LargeAsteroid, MediumAsteroid, SmallAsteroid derived from THAT? It's back to the whole inheritance problem again. I'm QUITE sure I'm missing something here...

This topic is closed to new replies.

Advertisement