Compare commits

..

No commits in common. "3aaa4557c6528ea2da6040f7178143900443ead8" and "c7f04c9d21cacb1264294c7e9e541b4b236e9bdb" have entirely different histories.

2 changed files with 45 additions and 63 deletions

View file

@ -1,4 +1,5 @@
#include <catch2/catch_test_macros.hpp> #include <catch2/catch_test_macros.hpp>
#include <string>
#define CATCH_CONFIG_MAIN #define CATCH_CONFIG_MAIN
#include <catch2/catch_all.hpp> #include <catch2/catch_all.hpp>
@ -73,9 +74,9 @@ TEST_CASE("Attach a simple component to an entity and verify it is correctly "
REQUIRE(w.has<ChoosenOne>(e2)); REQUIRE(w.has<ChoosenOne>(e2));
} }
struct Comp struct Name
{ {
int v = 0; std::string value;
}; };
TEST_CASE("Retrieve a component from an entity and verify its data matches " TEST_CASE("Retrieve a component from an entity and verify its data matches "
@ -84,13 +85,13 @@ TEST_CASE("Retrieve a component from an entity and verify its data matches "
world w; world w;
auto e = w.make_entity(); auto e = w.make_entity();
w.set(e, Comp()); w.set(e, Name{"zecsy!"});
REQUIRE(w.get<Comp>(e).v == 0); REQUIRE(w.get<Name>(e).value == "zecsy!");
w.get<Comp>(e).v = 77; w.get<Name>(e).value = "super-zecsy!";
REQUIRE(w.get<Comp>(e).v == 77); REQUIRE(w.get<Name>(e).value == "super-zecsy!");
} }
TEST_CASE( TEST_CASE(
@ -139,7 +140,7 @@ TEST_CASE("Addresses of removed components should be reused")
* Gotta reverse it because now we reuse ids in LIFO order * Gotta reverse it because now we reuse ids in LIFO order
*/ */
std::reverse(addr.begin(), addr.end()); std::reverse(addr.begin(), addr.end());
for(int j = 0; j < N; ++j) for(int j = 0; j < N; ++j)
{ {
REQUIRE(&w.get<ChoosenOne>(entities[j]) == addr[j]); REQUIRE(&w.get<ChoosenOne>(entities[j]) == addr[j]);
@ -160,15 +161,15 @@ TEST_CASE("Attach multiple components to an entity and verify all are "
world w; world w;
auto e = w.make_entity(); auto e = w.make_entity();
w.set(e, ChoosenOne{}, Comp{}); w.set(e, ChoosenOne{}, Name{"zecsy"});
REQUIRE(w.has<ChoosenOne, Comp>(e)); REQUIRE(w.has<ChoosenOne, Name>(e));
w.remove<ChoosenOne, Comp>(e); w.remove<ChoosenOne, Name>(e);
REQUIRE_FALSE(w.has<ChoosenOne, Comp>(e)); REQUIRE_FALSE(w.has<ChoosenOne, Name>(e));
REQUIRE_FALSE(w.has<ChoosenOne>(e)); REQUIRE_FALSE(w.has<ChoosenOne>(e));
REQUIRE_FALSE(w.has<Comp>(e)); REQUIRE_FALSE(w.has<Name>(e));
} }
TEST_CASE("Create a simple system that processes entities with a specific " TEST_CASE("Create a simple system that processes entities with a specific "

View file

@ -1,13 +1,11 @@
#pragma once #pragma once
#include <algorithm> #include <algorithm>
#include <concepts>
#include <cstdint> #include <cstdint>
#include <cstdlib> #include <cstdlib>
#include <format> #include <format>
#include <functional> #include <functional>
#include <set> #include <set>
#include <stdexcept> #include <stdexcept>
#include <type_traits>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
@ -15,23 +13,6 @@ namespace zecsy
{ {
using entity_id = uint64_t; using entity_id = uint64_t;
/*
* Actually, not a pure POD. Gotta figure out a better name
*/
template<typename... T>
concept Component = []
{
static_assert((std::is_default_constructible_v<T> && ...),
"Should have a default constructor");
static_assert((std::is_trivially_copyable_v<T> && ...),
"Should be trivially copyable");
static_assert((std::is_trivially_destructible_v<T> && ...),
"Should be trivially destructible");
static_assert((std::is_standard_layout_v<T> && ...),
"Should have standard layout");
return true;
}();
/* /*
* Using std::set for entities_set to maintain sorted order, which can * Using std::set for entities_set to maintain sorted order, which can
* improve cache locality during queries and iterations. * improve cache locality during queries and iterations.
@ -41,32 +22,32 @@ namespace zecsy
class component_storage final class component_storage final
{ {
public: public:
template<Component T> template<typename T>
bool has(entity_id e) const; bool has(entity_id e) const;
template<Component First, Component Second, Component... Rest> template<typename First, typename Second, typename... Rest>
bool has(entity_id e) const; bool has(entity_id e) const;
template<Component T> template<typename T>
T& get(entity_id e); T& get(entity_id e);
template<Component T> template<typename T>
void set(entity_id e); void set(entity_id e);
template<Component T> template<typename T>
void set(entity_id e, const T& comp); void set(entity_id e, const T& comp);
template<Component First, Component Second, Component... Rest> template<typename First, typename Second, typename... Rest>
void set(entity_id e); void set(entity_id e);
template<Component First, Component Second, Component... Rest> template<typename First, typename Second, typename... Rest>
void set(entity_id e, const First& comp0, const Second& comp1, void set(entity_id e, const First& comp0, const Second& comp1,
const Rest&... rest_comps); const Rest&... rest_comps);
template<Component T> template<typename T>
void remove(entity_id e); void remove(entity_id e);
template<Component First, Component Second, Component... Rest> template<typename First, typename Second, typename... Rest>
void remove(entity_id e); void remove(entity_id e);
private: private:
@ -94,7 +75,7 @@ namespace zecsy
inline component_storage::comp_id component_storage::next_component_id = 0; inline component_storage::comp_id component_storage::next_component_id = 0;
template<Component T> template<typename T>
inline bool component_storage::has(entity_id e) const inline bool component_storage::has(entity_id e) const
{ {
auto id = get_component_id<T>(); auto id = get_component_id<T>();
@ -105,7 +86,7 @@ namespace zecsy
return false; return false;
} }
template<Component T> template<typename T>
inline T& component_storage::get(entity_id e) inline T& component_storage::get(entity_id e)
{ {
auto id = get_component_id<T>(); auto id = get_component_id<T>();
@ -120,7 +101,7 @@ namespace zecsy
return *reinterpret_cast<T*>(&pool.data[index * sizeof(T)]); return *reinterpret_cast<T*>(&pool.data[index * sizeof(T)]);
} }
template<Component T> template<typename T>
inline void component_storage::set(entity_id e, const T& comp) inline void component_storage::set(entity_id e, const T& comp)
{ {
auto id = get_component_id<T>(); auto id = get_component_id<T>();
@ -143,13 +124,13 @@ namespace zecsy
pool.index_to_entity[index] = e; pool.index_to_entity[index] = e;
} }
template<Component T> template<typename T>
inline void component_storage::set(entity_id e) inline void component_storage::set(entity_id e)
{ {
set(e, T{}); set(e, T{});
} }
template<Component T> template<typename T>
inline void component_storage::remove(entity_id e) inline void component_storage::remove(entity_id e)
{ {
auto id = get_component_id<T>(); auto id = get_component_id<T>();
@ -172,13 +153,13 @@ namespace zecsy
pool.index_to_entity.erase(index); pool.index_to_entity.erase(index);
} }
template<Component First, Component Second, Component... Rest> template<typename First, typename Second, typename... Rest>
inline bool component_storage::has(entity_id e) const inline bool component_storage::has(entity_id e) const
{ {
return has<First>(e) && has<Second>(e) && (has<Rest>(e) && ...); return has<First>(e) && has<Second>(e) && (has<Rest>(e) && ...);
} }
template<Component First, Component Second, Component... Rest> template<typename First, typename Second, typename... Rest>
inline void component_storage::set(entity_id e) inline void component_storage::set(entity_id e)
{ {
set(e, First{}); set(e, First{});
@ -186,7 +167,7 @@ namespace zecsy
(set(e, Rest{}), ...); (set(e, Rest{}), ...);
} }
template<Component First, Component Second, Component... Rest> template<typename First, typename Second, typename... Rest>
inline void component_storage::set(entity_id e, const First& comp0, inline void component_storage::set(entity_id e, const First& comp0,
const Second& comp1, const Second& comp1,
const Rest&... rest_comps) const Rest&... rest_comps)
@ -196,7 +177,7 @@ namespace zecsy
(set(e, rest_comps), ...); (set(e, rest_comps), ...);
} }
template<Component First, Component Second, Component... Rest> template<typename First, typename Second, typename... Rest>
inline void component_storage::remove(entity_id e) inline void component_storage::remove(entity_id e)
{ {
remove<First>(e); remove<First>(e);
@ -257,23 +238,23 @@ namespace zecsy
void destroy_entity(entity_id e); void destroy_entity(entity_id e);
bool is_alive(entity_id e) const; bool is_alive(entity_id e) const;
template<Component... T> template<typename... T>
bool has(entity_id e) const; bool has(entity_id e) const;
template<Component T> template<typename T>
T& get(entity_id e); T& get(entity_id e);
template<Component... T> template<typename... T>
void set(entity_id e); void set(entity_id e);
template<Component... T> template<typename... T>
void set(entity_id e, const T&... comps); void set(entity_id e, const T&... comps);
template<Component... T> template<typename... T>
void remove(entity_id e); void remove(entity_id e);
template<Component... T> template<typename... T>
void query(std::invocable<T&...> auto&& system); void query(auto&& system);
private: private:
entities_set alive_entities; entities_set alive_entities;
@ -298,38 +279,38 @@ namespace zecsy
return alive_entities.contains(e); return alive_entities.contains(e);
} }
template<Component... T> template<typename... T>
inline bool world::has(entity_id e) const inline bool world::has(entity_id e) const
{ {
return storage.has<T...>(e); return storage.has<T...>(e);
} }
template<Component T> template<typename T>
inline T& world::get(entity_id e) inline T& world::get(entity_id e)
{ {
return storage.get<T>(e); return storage.get<T>(e);
} }
template<Component... T> template<typename... T>
inline void world::set(entity_id e) inline void world::set(entity_id e)
{ {
storage.set<T...>(e); storage.set<T...>(e);
} }
template<Component... T> template<typename... T>
inline void world::set(entity_id e, const T&... comps) inline void world::set(entity_id e, const T&... comps)
{ {
storage.set(e, comps...); storage.set(e, comps...);
} }
template<Component... T> template<typename... T>
inline void world::remove(entity_id e) inline void world::remove(entity_id e)
{ {
storage.remove<T...>(e); storage.remove<T...>(e);
} }
template<Component... T> template<typename... T>
inline void world::query(std::invocable<T&...> auto&& system) inline void world::query(auto&& system)
{ {
for(auto e: alive_entities) for(auto e: alive_entities)
{ {