Bye-bye entity wrapper
This commit is contained in:
parent
12f2bf3474
commit
3b8234655d
2 changed files with 46 additions and 125 deletions
|
@ -15,7 +15,6 @@ TEST_CASE("Create a single entity and verify its existence")
|
|||
auto e = w.make_entity();
|
||||
|
||||
REQUIRE(w.is_alive(e));
|
||||
REQUIRE(e.is_alive());
|
||||
}
|
||||
|
||||
TEST_CASE("Destroy an entity and ensure it no longer exists in the world")
|
||||
|
@ -26,7 +25,6 @@ TEST_CASE("Destroy an entity and ensure it no longer exists in the world")
|
|||
w.destroy_entity(e);
|
||||
|
||||
REQUIRE_FALSE(w.is_alive(e));
|
||||
REQUIRE_FALSE(e.is_alive());
|
||||
}
|
||||
|
||||
TEST_CASE("Entity #0 should be reserved and never used")
|
||||
|
@ -36,8 +34,7 @@ TEST_CASE("Entity #0 should be reserved and never used")
|
|||
auto e = w.make_entity();
|
||||
|
||||
REQUIRE(e != 0);
|
||||
REQUIRE(entity() == 0);
|
||||
REQUIRE_FALSE(entity().is_alive());
|
||||
REQUIRE_FALSE(w.is_alive(0));
|
||||
}
|
||||
|
||||
struct ChoosenOne
|
||||
|
@ -52,7 +49,6 @@ TEST_CASE("Entity shouldn't have a component that wasn't attached to it")
|
|||
auto e = w.make_entity();
|
||||
|
||||
REQUIRE_FALSE(w.has<ChoosenOne>(e));
|
||||
REQUIRE_FALSE(e.has<ChoosenOne>());
|
||||
}
|
||||
|
||||
TEST_CASE("Attempt of getting non-owned component should throw")
|
||||
|
@ -62,7 +58,6 @@ TEST_CASE("Attempt of getting non-owned component should throw")
|
|||
auto e = w.make_entity();
|
||||
|
||||
REQUIRE_THROWS(w.get<ChoosenOne>(e));
|
||||
REQUIRE_THROWS(e.get<ChoosenOne>());
|
||||
}
|
||||
|
||||
TEST_CASE("Attach a simple component to an entity and verify it is correctly associated")
|
||||
|
@ -70,15 +65,13 @@ TEST_CASE("Attach a simple component to an entity and verify it is correctly ass
|
|||
world w;
|
||||
|
||||
auto e1 = w.make_entity();
|
||||
e1.set(ChoosenOne{});
|
||||
w.set(e1, ChoosenOne{});
|
||||
|
||||
REQUIRE(e1.has<ChoosenOne>());
|
||||
REQUIRE(w.has<ChoosenOne>(e1));
|
||||
|
||||
auto e2 = w.make_entity();
|
||||
w.set(e2, ChoosenOne{});
|
||||
|
||||
REQUIRE(e2.has<ChoosenOne>());
|
||||
REQUIRE(w.has<ChoosenOne>(e2));
|
||||
}
|
||||
|
||||
|
@ -92,13 +85,13 @@ TEST_CASE("Retrieve a component from an entity and verify its data matches what
|
|||
world w;
|
||||
|
||||
auto e = w.make_entity();
|
||||
e.set(Name{"zecsy!"});
|
||||
w.set(e, Name{"zecsy!"});
|
||||
|
||||
REQUIRE(e.get<Name>().value == "zecsy!");
|
||||
REQUIRE(w.get<Name>(e).value == "zecsy!");
|
||||
|
||||
e.get<Name>().value = "super-zecsy!";
|
||||
w.get<Name>(e).value = "super-zecsy!";
|
||||
|
||||
REQUIRE(e.get<Name>().value == "super-zecsy!");
|
||||
REQUIRE(w.get<Name>(e).value == "super-zecsy!");
|
||||
}
|
||||
|
||||
TEST_CASE("Remove a component from an entity and verify it is no longer attached")
|
||||
|
@ -106,12 +99,12 @@ TEST_CASE("Remove a component from an entity and verify it is no longer attached
|
|||
world w;
|
||||
|
||||
auto e = w.make_entity();
|
||||
e.set(ChoosenOne{});
|
||||
REQUIRE_NOTHROW(e.remove<ChoosenOne>());
|
||||
w.set(e, ChoosenOne{});
|
||||
REQUIRE_NOTHROW(w.remove<ChoosenOne>(e));
|
||||
|
||||
REQUIRE_FALSE(e.has<ChoosenOne>());
|
||||
REQUIRE_FALSE(w.has<ChoosenOne>(e));
|
||||
|
||||
e.set(ChoosenOne{});
|
||||
w.set(e, ChoosenOne{});
|
||||
REQUIRE_NOTHROW(w.remove<ChoosenOne>(e));
|
||||
|
||||
REQUIRE_FALSE(w.has<ChoosenOne>(e));
|
||||
|
@ -120,7 +113,7 @@ TEST_CASE("Remove a component from an entity and verify it is no longer attached
|
|||
TEST_CASE("Addresses of removed components should be reused")
|
||||
{
|
||||
world w;
|
||||
std::vector<entity> entities;
|
||||
std::vector<entity_id> entities;
|
||||
std::vector<ChoosenOne*> addr;
|
||||
|
||||
const int N = 4;
|
||||
|
@ -130,27 +123,27 @@ TEST_CASE("Addresses of removed components should be reused")
|
|||
for(int j = 0; j < N; ++j)
|
||||
{
|
||||
entities.emplace_back(w.make_entity());
|
||||
entities.back().set<ChoosenOne>();
|
||||
w.set<ChoosenOne>(entities.back());
|
||||
}
|
||||
|
||||
if(addr.empty())
|
||||
{
|
||||
for(int j = 0; j < N; ++j)
|
||||
{
|
||||
addr.emplace_back(&entities[j].get<ChoosenOne>());
|
||||
addr.emplace_back(&w.get<ChoosenOne>(entities[j]));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int j = 0; j < N; ++j)
|
||||
{
|
||||
REQUIRE(&entities[j].get<ChoosenOne>() == addr[j]);
|
||||
REQUIRE(&w.get<ChoosenOne>(entities[j]) == addr[j]);
|
||||
}
|
||||
}
|
||||
|
||||
for(auto e: entities)
|
||||
{
|
||||
e.remove<ChoosenOne>();
|
||||
w.remove<ChoosenOne>(e);
|
||||
}
|
||||
entities.clear();
|
||||
}
|
||||
|
@ -161,17 +154,15 @@ TEST_CASE("Attach multiple components to an entity and verify all are correctly
|
|||
world w;
|
||||
|
||||
auto e = w.make_entity();
|
||||
e.set(ChoosenOne{}, Name{"zecsy"});
|
||||
w.set(e, ChoosenOne{}, Name{"zecsy"});
|
||||
|
||||
REQUIRE(e.has<ChoosenOne, Name>());
|
||||
REQUIRE(w.has<ChoosenOne, Name>(e));
|
||||
|
||||
e.remove<ChoosenOne, Name>();
|
||||
w.remove<ChoosenOne, Name>(e);
|
||||
|
||||
REQUIRE_FALSE(e.has<ChoosenOne, Name>());
|
||||
REQUIRE_FALSE(w.has<ChoosenOne, Name>(e));
|
||||
REQUIRE_FALSE(e.has<ChoosenOne>());
|
||||
REQUIRE_FALSE(e.has<Name>());
|
||||
REQUIRE_FALSE(w.has<ChoosenOne>(e));
|
||||
REQUIRE_FALSE(w.has<Name>(e));
|
||||
}
|
||||
|
||||
TEST_CASE("Create a simple system that processes entities with a specific component and verify it executes correctly")
|
||||
|
@ -184,11 +175,11 @@ TEST_CASE("Create a simple system that processes entities with a specific compon
|
|||
world w;
|
||||
auto e0 = w.make_entity(), e1 = w.make_entity();
|
||||
|
||||
e0.set<Component>(); //or e0.set(Component{})
|
||||
e1.set(Component{20});
|
||||
w.set<Component>(e0); //or e0.set(Component{})
|
||||
w.set(e1, Component{20});
|
||||
|
||||
REQUIRE(e0.get<Component>().value == 0);
|
||||
REQUIRE(e1.get<Component>().value == 20);
|
||||
REQUIRE(w.get<Component>(e0).value == 0);
|
||||
REQUIRE(w.get<Component>(e1).value == 20);
|
||||
|
||||
/*
|
||||
* Really wanna deduce it to w.query([](Component&){}),
|
||||
|
@ -199,8 +190,8 @@ TEST_CASE("Create a simple system that processes entities with a specific compon
|
|||
c.value++;
|
||||
});
|
||||
|
||||
REQUIRE(e0.get<Component>().value == 1);
|
||||
REQUIRE(e1.get<Component>().value == 21);
|
||||
REQUIRE(w.get<Component>(e0).value == 1);
|
||||
REQUIRE(w.get<Component>(e1).value == 21);
|
||||
}
|
||||
|
||||
TEST_CASE("Test a system’s ability to query and process only entities with a specific combination of components")
|
||||
|
@ -218,18 +209,18 @@ TEST_CASE("Test a system’s ability to query and process only entities with a s
|
|||
world w;
|
||||
|
||||
auto e0 = w.make_entity();
|
||||
e0.set(C0{}, C1{});
|
||||
w.set(e0, C0{}, C1{});
|
||||
|
||||
auto e1 = w.make_entity();
|
||||
e1.set(C0{});
|
||||
w.set(e1, C0{});
|
||||
|
||||
auto e2 = w.make_entity();
|
||||
e2.set(C1{});
|
||||
w.set(e2, C1{});
|
||||
|
||||
int count = 0;
|
||||
|
||||
REQUIRE(e0.get<C0>().value == 0);
|
||||
REQUIRE(e0.get<C1>().value == 10);
|
||||
REQUIRE(w.get<C0>(e0).value == 0);
|
||||
REQUIRE(w.get<C1>(e0).value == 10);
|
||||
|
||||
w.query<C0, C1>([&count](C0& c0, C1& c1)
|
||||
{
|
||||
|
@ -237,12 +228,12 @@ TEST_CASE("Test a system’s ability to query and process only entities with a s
|
|||
c1.value++;
|
||||
});
|
||||
|
||||
REQUIRE(e0.get<C0>().value == 1);
|
||||
REQUIRE(e0.get<C1>().value == 11);
|
||||
REQUIRE(w.get<C0>(e0).value == 1);
|
||||
REQUIRE(w.get<C1>(e0).value == 11);
|
||||
|
||||
REQUIRE(e1.get<C0>().value == 0);
|
||||
REQUIRE(e2.get<C1>().value == 10);
|
||||
REQUIRE(w.get<C0>(e1).value == 0);
|
||||
REQUIRE(w.get<C1>(e2).value == 10);
|
||||
|
||||
REQUIRE_FALSE(e1.has<C1>());
|
||||
REQUIRE_FALSE(e2.has<C0>());
|
||||
REQUIRE_FALSE(w.has<C1>(e1));
|
||||
REQUIRE_FALSE(w.has<C0>(e2));
|
||||
}
|
||||
|
|
90
zecsy.hpp
90
zecsy.hpp
|
@ -1,8 +1,6 @@
|
|||
#pragma once
|
||||
#include <catch2/internal/catch_console_colour.hpp>
|
||||
#include <cstdint>
|
||||
#include <format>
|
||||
#include <functional>
|
||||
#include <queue>
|
||||
#include <stdexcept>
|
||||
#include <typeindex>
|
||||
|
@ -22,36 +20,7 @@ namespace zecsy
|
|||
*/
|
||||
using entities_set = std::set<entity_id>;
|
||||
|
||||
class entity final
|
||||
{
|
||||
public:
|
||||
entity(class world* w, entity_id id);
|
||||
|
||||
entity() = default;
|
||||
operator entity_id() const;
|
||||
|
||||
bool is_alive() const;
|
||||
|
||||
template<typename... T>
|
||||
bool has() const;
|
||||
|
||||
template<typename T>
|
||||
T& get();
|
||||
|
||||
template<typename... T>
|
||||
void set();
|
||||
|
||||
template<typename... T>
|
||||
void set(const T&... comps);
|
||||
|
||||
template<typename... T>
|
||||
void remove();
|
||||
private:
|
||||
entity_id id = 0;
|
||||
class world* w = nullptr;
|
||||
};
|
||||
|
||||
class component_storage
|
||||
class component_storage final
|
||||
{
|
||||
public:
|
||||
template<typename T>
|
||||
|
@ -104,7 +73,7 @@ namespace zecsy
|
|||
class world final
|
||||
{
|
||||
public:
|
||||
entity make_entity();
|
||||
entity_id make_entity();
|
||||
void destroy_entity(entity_id e);
|
||||
bool is_alive(entity_id e) const;
|
||||
|
||||
|
@ -131,27 +100,12 @@ namespace zecsy
|
|||
component_storage storage;
|
||||
};
|
||||
|
||||
inline entity::entity(class world* w, entity_id id): w(w), id(id)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
inline entity::operator entity_id() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
inline bool entity::is_alive() const
|
||||
{
|
||||
return w && w->is_alive(id);
|
||||
}
|
||||
|
||||
inline entity world::make_entity()
|
||||
inline entity_id world::make_entity()
|
||||
{
|
||||
auto id = ++entity_counter;
|
||||
alive_entities.emplace(id);
|
||||
|
||||
return entity(this, id);
|
||||
return id;
|
||||
}
|
||||
|
||||
inline void world::destroy_entity(entity_id e)
|
||||
|
@ -191,30 +145,12 @@ namespace zecsy
|
|||
return *ptr;
|
||||
}
|
||||
|
||||
template<typename... T>
|
||||
inline bool entity::has() const
|
||||
{
|
||||
return w->has<T...>(id);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T& world::get(entity_id e)
|
||||
{
|
||||
return storage.get<T>(e);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T& entity::get()
|
||||
{
|
||||
return w->get<T>(id);
|
||||
}
|
||||
|
||||
template<typename... T>
|
||||
inline void entity::set()
|
||||
{
|
||||
(set(T{}), ...);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void component_storage::set(entity_id e, const T& comp)
|
||||
{
|
||||
|
@ -246,6 +182,12 @@ namespace zecsy
|
|||
indices_dict[typeid(T)][e] = index;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void component_storage::set(entity_id e)
|
||||
{
|
||||
set(e, T{});
|
||||
}
|
||||
|
||||
template<typename... T>
|
||||
inline void world::set(entity_id e)
|
||||
{
|
||||
|
@ -258,12 +200,6 @@ namespace zecsy
|
|||
storage.set(e, comps...);
|
||||
}
|
||||
|
||||
template<typename... T>
|
||||
inline void entity::set(const T&... comps)
|
||||
{
|
||||
w->set(id, comps...);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void component_storage::remove(entity_id e)
|
||||
{
|
||||
|
@ -283,12 +219,6 @@ namespace zecsy
|
|||
storage.remove<T...>(e);
|
||||
}
|
||||
|
||||
template<typename... T>
|
||||
inline void entity::remove()
|
||||
{
|
||||
w->remove<T...>(id);
|
||||
}
|
||||
|
||||
template<typename... T>
|
||||
inline bool world::has(entity_id e) const
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue