Поддержание полиморфизма в системе компонент-сущность - PullRequest
0 голосов
/ 29 декабря 2018

Я писал систему компонент-сущность и столкнулся с тем, что должно быть общей проблемой: компонентами, которые зависят друг от друга.Я буду использовать пример:

Скажем, вы создаете компонент элемента, который содержит данные, общие для элементов (скажем, вес).Но тогда, что, если вы хотите сделать компонент оборудования?Любой элемент оборудования также ДОЛЖЕН быть элементом, поэтому у вас будет два зависимых компонента.Такого рода отношения казались подходящими для наследования, поэтому я создал наследующий компонент.

Вопрос в том, что мне теперь нужно два «слоя полиморфизма» и система тегов перечисления, которую я написалбольше не работаетКроме того, я, возможно, захочу позже разделить этот компонент оборудования на несколько типов.

#include <memory>
#include <map>

enum COMPONENT_TAG {
    COMP_BASE,
    COMP_ITEM,
    COMP_ITEM_EQUIP
};

struct VirtualBaseComponent { // component

    COMPONENT_TAG tag;
    virtual ~VirtualBaseComponent() = 0;
};
VirtualBaseComponent::~VirtualBaseComponent() {};

struct ItemComponent : public VirtualBaseComponent {
    COMPONENT_TAG tag = COMP_ITEM;
    ~ItemComponent() {};
};

struct EquipmentComponent : public ItemComponent {
    COMPONENT_TAG tag = COMP_ITEM_EQUIP;
    ~EquipmentComponent() {};
};

struct Entity {
    std::map<COMPONENT_TAG, std::unique_ptr<VirtualBaseComponent>> components;

    template <typename T>
    T* get_component(COMPONENT_TAG tag) {

        auto found = components.find(tag);
        VirtualBaseComponent* baseptr;
        if (found == components.end()) {
            baseptr = nullptr;
        } else {
            baseptr = found->second.get();
        }
        return dynamic_cast<T*>(baseptr);
    }
};

int main() {
    {
    //set up a random item (a box)
    Entity box;
    box.components.insert(std::make_pair(COMP_ITEM, std::make_unique<ItemComponent>()));

    //fetching a base component: ok, this works fine
    ItemComponent *boxptr = box.get_component<ItemComponent>(COMP_ITEM);
    //do_stuff(boxptr->item_property);
    }


    {// set up a sword
    Entity sword;
    sword.components.insert(std::make_pair(COMP_ITEM_EQUIP, std::make_unique<EquipmentComponent>()));

    //but here, if I actually want to use some "item property" of the sword not related to its equipment-ness...
    //oops! that retrieves a nullptr, because sword does not have a base item tag
    ItemComponent *swordptr = sword.get_component<ItemComponent>(COMP_ITEM);

    ItemComponent a = *swordptr; //dereferencing it crashes the program
    }


}

Итак, как мне настроить и извлечь эти типы компонентов полиморфным способом?Я думаю, у меня мог бы быть большой список проверок if на теги в методе get_component, но на первый взгляд это кажется мне глупым решением.

...