mardi 18 juin 2019

Is it possible to use inheritance to implement an ECS in c++?

I'm trying to architect a game I'm writing in C++ as an Entity/Component system (the basic idea being I would have a set of "Entity" classes representing different kinds of data and a set of "Component" classes representing various behaviors a given entity could have). I wanted to implement it using virtual base classes for the components. For instance, I could have a Character entity:

class Character {
public:
    int armor;
    int health;
    std::string name;
};

as well as a Fighter component representing something that can use melee weapons:

class Fighter {
public:
    int damage;
    virtual Direction attack() = 0;
}

and a Mage component representing something that can cast spells

class Mage {
public:
    std::vector<Spell> spellList;
    virtual Spell cast() = 0;
}

Using multiple inheritance to use these, I'd have

class ElvenMage : Character, Mage {
public:
    ElvenMage() {
        this->armor = 0;
        this->health = 10;
        this->name = "elven mage";
        this->spellList = ...;
    }
    virtual Spell cast() {
        // some AI logic to figure out which spell to cast
    }
};

and

class Player : Character, Fighter, Mage {
public:
    Player() {
        this->armor = 5;
        this->health = 20;
        this->name = "Player";
    }
    virtual Direction attack() {
        // some logic to handle player melee input
    }
    virtual Spell cast() {
        // some logic to handle player spell casting input
    }
};

To keep track of all current characters on the map I could do something like

class Engine {
public:
    std::vector<std::unique_ptr<Character>> characters;

I have to store them directly as Characters (not as Fighters or Mages), yet I would need to process fighters and mages separately (for instance, looping through all Characters and if they can cast a spell they do so otherwise they attack with a melee weapon). In the actual game logic, how would I distinguish between an instance of Character that also implements Mage vs. an instance of Character that also implements Fighter?

Is there an easy way to do what I am trying to, or should I completely rethink my design?

(note: this isn't actual code; in the real world I'd actually use a factory or something to create elves or whatever instead of trying to put all the information in the constructor, and I'd probably separate the logic differently, but it illustrates the problem I'm having).

Aucun commentaire:

Enregistrer un commentaire