Add support for data relationships
richardbiely opened this issue · 1 comments
richardbiely commented
Current roguelike example does something like this:
enum class ItemType : uint8_t { Poison, Potion, Arrow };
struct Item {
ItemType type;
};
poison = world.CreateEntity();
world.AddComponent<Item>(poison, {ItemType::Poison});
potion = world.CreateEntity();
world.AddComponent<Item>(potion, {ItemType:: Potion});
arrow = world.CreateEntity();
world.AddComponent<Item>(arrow, {ItemType:: Arrow});
auto q = world.CreateQuery().All<const Item>();
q.ForEach([](Item item){
if (item.type == ItemType::Poison) {
// the item is poisonous
} else if (item.type == ItemType::Potion) {
// potion here
} else if (item.type == ItemType::Arrow) {
// arrow
}
});
Each item is identified by an enum. While this might is be necessarily bad, it is not scalable.
What if we want to query all potions? Given the code above, we'd have to check each item:
containers::darray_ext<Item, 128> potions;
auto q = world.CreateQuery().All<const Item>();
q.ForEach([&](Item item){
if (item.type != ItemType::Potion)
continue;
potions.push_back(item);
});
// do something with potions now
// ....
Another solution would be creating a tag for each item type:
struct Poison{};
struct Potion{};
struct Arrow{};
struct Item {};
...
poison = world.CreateEntity();
world.AddComponent<Item>(poison);
world.AddComponent<Poison>(poison);
potion = world.CreateEntity();
world.AddComponent<Item>(potion);
world.AddComponent<Potion>(potion);
arrow = world.CreateEntity();
world.AddComponent<Item>(arrow);
world.AddComponent<Arrow>(arrow);
...
q.ForEach([&](Potion potion){
// ... do something with potions
}
But isn't this too much code? What if we could tell that each of those 3 specific item types actually are items?
struct Poison{};
struct Potion{};
struct Arrow{};
struct Item {};
...
world.Make<Poison>.Is<Item>();
world.Make<Potion>.Is<Item>();
world.Make<Arrow>.Is<Item>();
poison = world.CreateEntity();
world.AddComponent<Poison>(poison);
potion = world.CreateEntity();
world.AddComponent<Potion>(potion);
arrow = world.CreateEntity();
world.AddComponent<Arrow>(arrow);
auto q1 = world.CreateQuery().All<const Item>();
q1.ForEach([](Entity e){
// ... all these entities are Items by default.
// This covers Poison, Potion and Arrow as well!
});
auto q2 = world.CreateQuery().All<const Potion>();
q2.ForEach([&](Potion potion){
// ... do something with potions
}
This would give us something very powerful. Mostly when combined with new query traversal features.
This example is extremely basic so it might not fully describe the point, though.