Tuesday, August 15, 2017

Organizing classes 1/3

In most of game programs, It is the common problem that how to organize classes.

We have a class Player, Enemy, Obstacle, Bullet, ...and these objects' features are partially same, and partially different.And if it is a online game, it updates repeatedly.

Using inheritance


Let's dive into code.

// the Base class of all. has position data.
class Object
{
    int pos_x;
    int pos_y;
};

// Player class has input data, inherits Object.
class Player : public Object
{
    float input_dir;
};

// Enemy class has some kind of AI parameter, also inherites Object.
class Enemy : public Object
{
    int ai_param;
};

// Obstacle class has no data here, and inherits Object.
class Obstacle : public Object
{
};
Here we declare Object, Player, Enemy, Obstacle class.
In the sense of 'Inheritance', this organization seems meaningful.

Next, let's think to add data 'poisoned' which is bool value and represents the object get poisoned.
Well, what kind of object can get poisoned??
In this case, Player and Enemy. Obstacle can not get poisoned.

// Player class has input data, inherits Object.
class Player : public Object
{
    float input_dir;
    bool poisoned;
};

// Enemy class has some kind of AI parameter, also inherits Object.
class Enemy : public Object
{
    int ai_param;
    bool poisoned;
};

// Obstacle class has no data here, and inherits Object.
class Obstacle : public Object
{
};

Here we met some trouble... 'bool poisoned' is duplicated. This means poison-related implementation will duplicate too.
And in the future, when it comes to add 'cursed' or 'paralyzed', we will get same problem.

One idea to solve this problem is to create new base class.

//Living Object may got poisoned, paralyzed, ... and some other status.
class LivingObject : public Object {
{
    bool poisoned;
    bool paralyzed;
    ...
};

class Player : public LivingObject
{
    float input_dir;
};

class Enemy : public LivingObject
{
    int ai_param;
};

class Obstacle : public Object
{
};

Creating new class and make existing classes inherit the new class...easy! ...really?

Additionally, what if we need to declare data 'health'?
Ok, LivingObject has health.....No. It's not good. because we need 'health' for Obstacles in order to get destroyed by others.

Well, how can we re-organize the class tree !?
It's painful to re-organize the class tree. And if it's already released product, it will take big risk.

=> to be continued to next post.


No comments:

Post a Comment

It's magic! std::bind

'std::bind' is a powerful helper for working around 'std::function'. 'std::bind' makes a instance of 'std::fun...