12
\$\begingroup\$

I'm a beginner both in game developping and programming.

I'm trying to learn some principle in the building of a game engine.
I want to create a simple game, I'm at the point where I'm trying to implement the game engine.

So I thought my game engine should control this things:

- Moving the objects in the scene
- Checking the collisions
- Adjusting movements based on collisions
- Passing the polygons to the rendering engine

I designed my objects like this:

class GlObject{
private:
    idEnum ObjId;
    //other identifiers
public:
    void move_obj(); //the movements are the same for all the objects (nextpos = pos + vel)
    void rotate_obj(); //rotations are the same for every objects too
    virtual Polygon generate_mesh() = 0; // the polygons are different
}

and I have 4 different objects in my game: plane, obstacle, player, bullet and I designed them like this:

class Player : public GlObject{ 
private:
    std::string name;
public:
    Player();
    Bullet fire() const; //this method is unique to the class player
    void generate_mesh();
}

Now in the game engine I want to have a general object list where I can check for example for collision, move objects, and so on, but I want also that the game engine will take the user commands to control the player...

Is this a good Idea?

class GameEngine{
private:
    std::vector<GlObject*> objects; //an array containg all the object present
    Player* hPlayer; //hPlayer is to be read as human player, and is a pointer to hold the reference to an object inside the array
public:
    GameEngine();
    //other stuff
}

the GameEngine constructor will be like this:

GameEngine::GameEngine(){
    hPlayer = new Player;
    objects.push_back(hPlayer);
}

The fact that I'm using a pointer is because I need to call the fire() that is unique to the Player object.

So my question is: is it a good idea? Is my use of inheritance wrong here?

\$\endgroup\$
3
  • 2
    \$\begingroup\$ See also gamedev.stackexchange.com/questions/16677/… and gamedev.stackexchange.com/questions/22483/… \$\endgroup\$
    – MrCranky
    Commented Jan 30, 2012 at 11:32
  • \$\begingroup\$ I've seen them after posting, and actually composition is a great idea! I have always fear to end up using c with classes instead of having a real c++ design! \$\endgroup\$
    – Pella86
    Commented Jan 30, 2012 at 16:47
  • \$\begingroup\$ I think there are many more reasons to use composition than inheritance... My answer gives a few examples around the flexibility advantages it provides. For a good example of implementation check the articles I linked. \$\endgroup\$
    – Coyote
    Commented Feb 1, 2012 at 1:30

3 Answers 3

8
\$\begingroup\$

For the logics data and functions of your game objects (entities) I would strongly recommend using composition over inheritance. A good start would be the component based approach. It is well described in this Cowboy Programming article which describes how this architecture can be implemented and how it benefited the Tony Hawk franchise.

Also this article about entity systems inspired me when I first read it.

Inheritance is a great tool for polymorphism. Excepting for very simple projects you should avoid using it as a way to structure the entities and your game logics. If you go with inheritance you will most certainly end-up with having to replicate and maintain copies of the same code to implement functions that cannot be inherited from a common parent. And you will probably start polluting your classes with logics and data most commonly used to avoid replicating too much code.

Components are very handy in numerous situations. You can achieve much more using them :

Flexibility with your entity types: There are times in game development where some entities evolve suddenly and while the game designer makes the decision de developer will have to implement it. It takes just a few steps to add an existing behavior without replicating code. Component based systems allow more changes to be done by non programmers. For example each type of entity instead of being represented by a class can be represented by a description file which contains all the component names and parameters needed to configure the type. This allows non programmers to do and test changes without recompiling the game. Simply editing the description files will be enough to add, remove or change the components used by each entity type.

Flexibility with particular instances and specific scenarios: There are cases where you need your player to be able to equip weapons, or items, you can add an inventory component to your player. during the development of your game you will need other entities to have an inventory (enemies for example). And at one point you have in your scenario a situation where a tree is supposed to contain some sort of hidden item. With components you can add an inventory component even to entities which type is not designed originally to have one with no additional programming effort.

Flexibility at run time: Components offer a very effective way to change the behavior of entities at runtime. You can add and remove components at runtime and thus create or remove behaviors and properties when needed. They also allow you to separate different types of data into groups that can (sometimes) be computed separately in parallel on multiple GPUs.

Flexibility in time: Components can be used to keep compatibility between versions. For example when changes are made between releases of a game you can (not always) simply add new components which implement the new behaviors and changes. Then the game will instantiate the right components attached to your entities depending on the save file loaded, peer connected or server the player joins. This comes extremely handy in scenarios where you can't control the release dates of the new version on all platforms (Steam, Mac App Store, iPhone, Android...).

For a better insight take a look at the [component-based] and [entity-system] tagged questions.

\$\endgroup\$
13
\$\begingroup\$

Depends on what you mean by 'good'. It will get the job done, certainly. It has plenty of up-sides, and down-sides. You won't find them until your engine is much more complex. See this question on SO, for discussion on the subject.

There's plenty of opinions either way, but if your engine code is still at that early stage, it will be hard to explain to you why it might be bad.

In general, Scott Meyers has some great things to say on inheritance. If you're still at that stage in development, read this book (Effective C++) before you continue. It's a fantastic book, and is a requirement for any coders working at our company. But to sum up the advice: if you are writing a class and considering using inheritance, be absolutely clear that the relationship between the class and its ancestor is an 'is a' relationship. That is, every B is an A. Don't just use inheritance as an easy way to give B access to functionality A provides, that way will lead to severe architectural problems, and there are other ways to do it.

Put simply; for an engine of any size, you will quickly find that the objects rarely fall into a neat hierarchical structure for which inheritance works. Use it when it's appropriate, but don't fall into the trap of using it for everything - learn other ways to inter-relate objects.

\$\endgroup\$
1
  • \$\begingroup\$ I second the opinion about inheritance. My personal rule of thumb is: don't do it unless you have to or doing it any other way would be stupid. In other words, inheritance is bad idea in 99% of the cases (at least :) ). Also, it may be good to separate game logic (rotate/move) from rendering (generate_mesh()). Another thing is fire() -- consider having a list of actions and a generic action(my_action) function -- this way you won't end up with a bazillion different functions spread across all classes. In either case, keep it simple and refactor ruthlessly as you come across problems. \$\endgroup\$
    – Gilead
    Commented Jan 30, 2012 at 18:26
5
\$\begingroup\$

In general prefer composition to inheritance. http://www.artima.com/cppsource/codestandards3.html

Composition gives you more flexibility.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .