Compare commits
	
		
			2 commits
		
	
	
		
			c7f04c9d21
			...
			3aaa4557c6
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 3aaa4557c6 | |||
| 006d9fc95e | 
					 2 changed files with 63 additions and 45 deletions
				
			
		| 
						 | 
					@ -1,5 +1,4 @@
 | 
				
			||||||
#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>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -74,9 +73,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 Name
 | 
					struct Comp
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    std::string value;
 | 
					    int v = 0;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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 "
 | 
				
			||||||
| 
						 | 
					@ -85,13 +84,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, Name{"zecsy!"});
 | 
					    w.set(e, Comp());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    REQUIRE(w.get<Name>(e).value == "zecsy!");
 | 
					    REQUIRE(w.get<Comp>(e).v == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    w.get<Name>(e).value = "super-zecsy!";
 | 
					    w.get<Comp>(e).v = 77;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    REQUIRE(w.get<Name>(e).value == "super-zecsy!");
 | 
					    REQUIRE(w.get<Comp>(e).v == 77);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST_CASE(
 | 
					TEST_CASE(
 | 
				
			||||||
| 
						 | 
					@ -161,15 +160,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{}, Name{"zecsy"});
 | 
					    w.set(e, ChoosenOne{}, Comp{});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    REQUIRE(w.has<ChoosenOne, Name>(e));
 | 
					    REQUIRE(w.has<ChoosenOne, Comp>(e));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    w.remove<ChoosenOne, Name>(e);
 | 
					    w.remove<ChoosenOne, Comp>(e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    REQUIRE_FALSE(w.has<ChoosenOne, Name>(e));
 | 
					    REQUIRE_FALSE(w.has<ChoosenOne, Comp>(e));
 | 
				
			||||||
    REQUIRE_FALSE(w.has<ChoosenOne>(e));
 | 
					    REQUIRE_FALSE(w.has<ChoosenOne>(e));
 | 
				
			||||||
    REQUIRE_FALSE(w.has<Name>(e));
 | 
					    REQUIRE_FALSE(w.has<Comp>(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 "
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										83
									
								
								zecsy.hpp
									
									
									
									
									
								
							
							
						
						
									
										83
									
								
								zecsy.hpp
									
									
									
									
									
								
							| 
						 | 
					@ -1,11 +1,13 @@
 | 
				
			||||||
#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>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,6 +15,23 @@ 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.
 | 
				
			||||||
| 
						 | 
					@ -22,32 +41,32 @@ namespace zecsy
 | 
				
			||||||
    class component_storage final
 | 
					    class component_storage final
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        template<typename T>
 | 
					        template<Component T>
 | 
				
			||||||
        bool has(entity_id e) const;
 | 
					        bool has(entity_id e) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        template<typename First, typename Second, typename... Rest>
 | 
					        template<Component First, Component Second, Component... Rest>
 | 
				
			||||||
        bool has(entity_id e) const;
 | 
					        bool has(entity_id e) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        template<typename T>
 | 
					        template<Component T>
 | 
				
			||||||
        T& get(entity_id e);
 | 
					        T& get(entity_id e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        template<typename T>
 | 
					        template<Component T>
 | 
				
			||||||
        void set(entity_id e);
 | 
					        void set(entity_id e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        template<typename T>
 | 
					        template<Component T>
 | 
				
			||||||
        void set(entity_id e, const T& comp);
 | 
					        void set(entity_id e, const T& comp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        template<typename First, typename Second, typename... Rest>
 | 
					        template<Component First, Component Second, Component... Rest>
 | 
				
			||||||
        void set(entity_id e);
 | 
					        void set(entity_id e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        template<typename First, typename Second, typename... Rest>
 | 
					        template<Component First, Component Second, Component... 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<typename T>
 | 
					        template<Component T>
 | 
				
			||||||
        void remove(entity_id e);
 | 
					        void remove(entity_id e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        template<typename First, typename Second, typename... Rest>
 | 
					        template<Component First, Component Second, Component... Rest>
 | 
				
			||||||
        void remove(entity_id e);
 | 
					        void remove(entity_id e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
| 
						 | 
					@ -75,7 +94,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<typename T>
 | 
					    template<Component 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>();
 | 
				
			||||||
| 
						 | 
					@ -86,7 +105,7 @@ namespace zecsy
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    template<typename T>
 | 
					    template<Component 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>();
 | 
				
			||||||
| 
						 | 
					@ -101,7 +120,7 @@ namespace zecsy
 | 
				
			||||||
        return *reinterpret_cast<T*>(&pool.data[index * sizeof(T)]);
 | 
					        return *reinterpret_cast<T*>(&pool.data[index * sizeof(T)]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    template<typename T>
 | 
					    template<Component 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>();
 | 
				
			||||||
| 
						 | 
					@ -124,13 +143,13 @@ namespace zecsy
 | 
				
			||||||
        pool.index_to_entity[index] = e;
 | 
					        pool.index_to_entity[index] = e;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    template<typename T>
 | 
					    template<Component T>
 | 
				
			||||||
    inline void component_storage::set(entity_id e)
 | 
					    inline void component_storage::set(entity_id e)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        set(e, T{});
 | 
					        set(e, T{});
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    template<typename T>
 | 
					    template<Component 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>();
 | 
				
			||||||
| 
						 | 
					@ -153,13 +172,13 @@ namespace zecsy
 | 
				
			||||||
        pool.index_to_entity.erase(index);
 | 
					        pool.index_to_entity.erase(index);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    template<typename First, typename Second, typename... Rest>
 | 
					    template<Component First, Component Second, Component... 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<typename First, typename Second, typename... Rest>
 | 
					    template<Component First, Component Second, Component... Rest>
 | 
				
			||||||
    inline void component_storage::set(entity_id e)
 | 
					    inline void component_storage::set(entity_id e)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        set(e, First{});
 | 
					        set(e, First{});
 | 
				
			||||||
| 
						 | 
					@ -167,7 +186,7 @@ namespace zecsy
 | 
				
			||||||
        (set(e, Rest{}), ...);
 | 
					        (set(e, Rest{}), ...);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    template<typename First, typename Second, typename... Rest>
 | 
					    template<Component First, Component Second, Component... 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)
 | 
				
			||||||
| 
						 | 
					@ -177,7 +196,7 @@ namespace zecsy
 | 
				
			||||||
        (set(e, rest_comps), ...);
 | 
					        (set(e, rest_comps), ...);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    template<typename First, typename Second, typename... Rest>
 | 
					    template<Component First, Component Second, Component... Rest>
 | 
				
			||||||
    inline void component_storage::remove(entity_id e)
 | 
					    inline void component_storage::remove(entity_id e)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        remove<First>(e);
 | 
					        remove<First>(e);
 | 
				
			||||||
| 
						 | 
					@ -238,23 +257,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<typename... T>
 | 
					        template<Component... T>
 | 
				
			||||||
        bool has(entity_id e) const;
 | 
					        bool has(entity_id e) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        template<typename T>
 | 
					        template<Component T>
 | 
				
			||||||
        T& get(entity_id e);
 | 
					        T& get(entity_id e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        template<typename... T>
 | 
					        template<Component... T>
 | 
				
			||||||
        void set(entity_id e);
 | 
					        void set(entity_id e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        template<typename... T>
 | 
					        template<Component... T>
 | 
				
			||||||
        void set(entity_id e, const T&... comps);
 | 
					        void set(entity_id e, const T&... comps);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        template<typename... T>
 | 
					        template<Component... T>
 | 
				
			||||||
        void remove(entity_id e);
 | 
					        void remove(entity_id e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        template<typename... T>
 | 
					        template<Component... T>
 | 
				
			||||||
        void query(auto&& system);
 | 
					        void query(std::invocable<T&...> auto&& system);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
        entities_set alive_entities;
 | 
					        entities_set alive_entities;
 | 
				
			||||||
| 
						 | 
					@ -279,38 +298,38 @@ namespace zecsy
 | 
				
			||||||
        return alive_entities.contains(e);
 | 
					        return alive_entities.contains(e);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    template<typename... T>
 | 
					    template<Component... 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<typename T>
 | 
					    template<Component 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<typename... T>
 | 
					    template<Component... T>
 | 
				
			||||||
    inline void world::set(entity_id e)
 | 
					    inline void world::set(entity_id e)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        storage.set<T...>(e);
 | 
					        storage.set<T...>(e);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    template<typename... T>
 | 
					    template<Component... 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<typename... T>
 | 
					    template<Component... T>
 | 
				
			||||||
    inline void world::remove(entity_id e)
 | 
					    inline void world::remove(entity_id e)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        storage.remove<T...>(e);
 | 
					        storage.remove<T...>(e);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    template<typename... T>
 | 
					    template<Component... T>
 | 
				
			||||||
    inline void world::query(auto&& system)
 | 
					    inline void world::query(std::invocable<T&...> auto&& system)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        for(auto e: alive_entities)
 | 
					        for(auto e: alive_entities)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue