Using composition
In the previous post, we tried to implement some features of game object by class inheritance, but it was not so good for maintenance.Now, we will try to solve this problem by 'composite class'
// base class has interface to get all components, returning nullptr by default. class Object { public: virtual Input* input() { return nullptr; } virtual AIParam* ai_param() { return nullptr; } virtual Position position() { return nullptr; } virtual Health* health() { return nullptr; } virtual TimeStatus* time_status() { return nullptr; } }; // player class has actual component and returns its pointer. class Player : public Object { Input input; Position position; Health health; TimeStatus time_status; public: virtual Input* input() { return &input; } virtual Position position() { return &position; } virtual Health* health() { return &health; } virtual TimeStatus* time_status() { return &time_status; } }; // enemy class is same as Player except first field. class Enemy : public Object { AIParam ai_param; Position position; Health health; TimeStatus time_status; public: virtual AIParam* ai_param() { return &ai_param; } virtual Position position() { return &position; } virtual Health* health() { return &health; } virtual Health* time_status() { return &time_status; } }; // obstacle class has Position and Health. class Obstacle : public Object { Position position; Health health; public: virtual Position position() { return &position; } virtual Health* health() { return &health; } }; // Health component, implements apply_damage() class Health { Object* owner; int health; public: void apply_damage(int damage) { if( owner->time_status() ) { // calc damage by status; } health -= damage; } };
In this design, A derived classes is composed by feature classes(i.e., component) and has accessor function to each component.
Each component has pointer to Object in order to access other component.
for example, attack() function will look like this.
void attack(int damage, Object* obj) { if( obj->health() ) { obj->health()->apply_damage(damage); } }
Comparing previous design(using inheritance), it's easier to add/remove features.
But accessing components by getter function is not looks pretty.
Now, I propose an other idea in next post.
No comments:
Post a Comment