Поддержание полиморфизма в системе компонент-сущность

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

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

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

#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, но на первый взгляд это кажется мне глупым решением.

1

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector