Preview
Open Original
Heyya reddit, i am making a game engine as a hobby and i was wondering if anyone would like to give some feedback on my ECS implementation. (I haven’t measured it so idk about performance.)
What i want to know is that if this is a “correct” way to implement such a thing.
Thank you for the feedback.
#ifndef IKK_ECS_HPP
#define IKK_ECS_HPP
#include <unordered_map>
#include <algorithm>
#include <expected>
#include <vector>
#include "InariKonKon/Utility/NonConstructible.hpp"
#include "InariKonKon/ECS/Entities/Entity.hpp"
#include "InariKonKon/ECS/Systems/System.hpp"
#include "InariKonKon/Utility/Error.hpp"
namespace ikk
{
class ECS final : public NonConstructible
{
public:
template<std::derived_from<Component> T>
static void addComponentToEntity(const Entity& entity, T&& co...
Heyya reddit, i am making a game engine as a hobby and i was wondering if anyone would like to give some feedback on my ECS implementation. (I haven’t measured it so idk about performance.)
What i want to know is that if this is a “correct” way to implement such a thing.
Thank you for the feedback.
#ifndef IKK_ECS_HPP
#define IKK_ECS_HPP
#include <unordered_map>
#include <algorithm>
#include <expected>
#include <vector>
#include "InariKonKon/Utility/NonConstructible.hpp"
#include "InariKonKon/ECS/Entities/Entity.hpp"
#include "InariKonKon/ECS/Systems/System.hpp"
#include "InariKonKon/Utility/Error.hpp"
namespace ikk
{
class ECS final : public NonConstructible
{
public:
template<std::derived_from<Component> T>
static void addComponentToEntity(const Entity& entity, T&& component) noexcept;
template<std::derived_from<Component> T>
static void removeComponentFromEntity(const Entity& entity) noexcept;
template<std::derived_from<Component> T>
[[nodiscard]] static std::expected<T*, Error> getComponentForEntity(const Entity& entity) noexcept;
template<std::derived_from<Component> T>
[[nodiscard]] static const std::vector<T> getComponents() noexcept;
template<std::derived_from<Component> T>
[[nodiscard]] static const std::vector<Entity> getEntitiesWith() noexcept;
template<DerivedFromSystem T>
static void applySystemOnEntity(const Entity& entity) noexcept;
private:
template<std::derived_from<Component> T>
[[nodiscard]] static std::unordered_map<Entity, T>& getComponentMap();
};
template<std::derived_from<Component> T>
void ECS::addComponentToEntity(const Entity& entity, T&& component) noexcept
{
std::unordered_map<Entity, T>& map = getComponentMap<T>();
if (map.contains(entity) == false)
map.emplace(entity, std::move(component));
}
template<std::derived_from<Component> T>
void ECS::removeComponentFromEntity(const Entity& entity) noexcept
{
std::unordered_map<Entity, T>& map = getComponentMap<T>();
if (map.contains(entity))
map.erase(entity);
}
template<std::derived_from<Component> T>
std::expected<T*, Error> ECS::getComponentForEntity(const Entity& entity) noexcept
{
std::unordered_map<Entity, T>& map = getComponentMap<T>();
if (map.contains(entity) == false)
return std::unexpected(Error{ "Entity does not have the requested component." });
else
return std::expected<T*, Error>{ &map.at(entity) };
}
template<std::derived_from<Component> T>
const std::vector<T> ECS::getComponents() noexcept
{
const std::unordered_map<Entity, T>& map = getComponentMap<T>();
std::vector<T> values{};
values.reserve(map.size());
std::transform(map.cbegin(), map.cend(), std::back_inserter(values),
[](const std::pair<Entity, T>& pair){ return pair.second; });
return values;
}
template<std::derived_from<Component> T>
const std::vector<Entity> ECS::getEntitiesWith() noexcept
{
const std::unordered_map<Entity, T>& map = getComponentMap<T>();
std::vector<Entity> values{};
values.reserve(map.size());
std::transform(map.cbegin(), map.cend(), std::back_inserter(values),
[](const std::pair<Entity, T>& pair){ return pair.first; });
return values;
}
template<DerivedFromSystem T>
void ECS::applySystemOnEntity(const Entity& entity) noexcept
{
std::expected<typename T::ComponentType*, Error> temp = getComponentForEntity<typename T::ComponentType>(entity);
if (temp.has_value())
T{}(*temp.value());
}
template<std::derived_from<Component> T>
std::unordered_map<Entity, T>& ECS::getComponentMap()
{
static std::unordered_map<Entity, T> instance{};
return instance;
}
}
#endif