Entt介绍¶
由于EnTT的System
部分由用户自己编写,所以EnTT并没有提供任何System
并行支持,本系列也不会说。并行支持部分可自行参阅flecs源码。
EnTT
是一个仅有头的、微小的、易于使用的库,用于游戏编程以及用现代C++编写的更多内容
面是一个简短的,但不完整的清单,它今天提供了什么。
- 内建的RTTI系统与标准系统相似。
- 一个
constexpr
工具,用于人类可读的资源名称。 - 使用单态模式建立的最小的配置系统。
- 令人难以置信的快速的实体-组件系统,它有自己的_付费_政策。
- 视图和组来迭代实体和组件,并允许不同的访问模式,从完美的SoA到完全随机。
- 在实体-组件系统的基础上建立了很多设施,以帮助用户,避免重新发明轮子。
- 见过的最小和最基本的服务定位器的实现。
- 一个内置的、非侵入性的、无宏的运行时反射系统。
- 静态多态性变得简单,每个人都可以做到。
- 一些自制的容器,如基于稀疏集的哈希图。
- 一个适用于任何类型进程的合作调度器。
- 资源管理所需的一切(缓存、加载器、手柄)。
- 代表、信号处理程序和一个小小的事件调度器。
- 一个通用的事件发射器,作为一个基于CRTP习语的类模板。
- 还有更多!请看 维基.
把这些列表看作是正在进行的工作,也是项目的一部分。整个API对于那些敢于阅读它的人来说是有完整的代码记录的。
请注意,现在所有的工具也都是DLL友好的,并且可以跨边界顺利运行。
大多数人都知道的一件事是,EnTT
也被用于Minecraft。
组件类Component.h¶
单独存放各种组件(也许后面还可以再分细点)。
* 不需要做任何继承
* 只需要提供:参数+构造方法+运算符
* 运算符重载:运算符重载允许 TransformComponent
实例被当作 glm::mat4
类型的左值引用使用。这意味着你可以像操作 glm::mat4
对象一样直接操作 TransformComponent
实例的 Transform
成员变量。
* 举个栗子:
cpp
void DoSomethingWithTransform(const glm::mat4& transform) {
// ...
}
TransformComponent tc;
DoSomethingWithTransform(tc); // 直接传递实例,不需要显式访问 Transform 成员变量
#pragma once
#include <glm/glm.hpp>
namespace CryDust {
struct TransformComponent
{
glm::mat4 Transform{ 1.0f };
TransformComponent() = default;
TransformComponent(const TransformComponent&) = default;
TransformComponent(const glm::mat4& transform)
: Transform(transform) {}
operator glm::mat4& () { return Transform; }
operator const glm::mat4& () const { return Transform; }
};
struct SpriteRendererComponent
{
glm::vec4 Color{ 1.0f, 1.0f, 1.0f, 1.0f };
SpriteRendererComponent() = default;
SpriteRendererComponent(const SpriteRendererComponent&) = default;
SpriteRendererComponent(const glm::vec4& color)
: Color(color) {}
};
}
Scene类¶
构造¶
- 使用registry.create创建一个entity
- m_Registry.emplace添加组件,如TransformComponent
其他¶
-
registry注册表:包含了组件数据
-
DoMath():用来处理数学变换
- OnTransformConstruct()::用于绑定组件构造,需要提供一个registry参数和entity参数
- Scene()
- CreateEntity()
- OnUpdate(ts):拿到registry的group中的组件,遍历调用,并逐个绘制对应的Mesh
#pragma once #include "entt.hpp" #include "CryDust/Core/Timestep.h" namespace CryDust { class Scene { public: Scene(); ~Scene(); entt::entity CreateEntity(); //创建实体 // TEMP entt::registry& Reg() { return m_Registry; } //注册实体 void OnUpdate(Timestep ts); private: entt::registry m_Registry;//注册 }; }
CPP¶
#include "cdpch.h"
#include "Scene.h"
#include "Components.h"
#include "CryDust/Renderer/Renderer2D.h"
#include <glm/glm.hpp>
namespace CryDust {
static void DoMath(const glm::mat4& transform)
{
}
static void OnTransformConstruct(entt::registry& registry, entt::entity entity)
{
}
Scene::Scene()
{
#if ENTT_EXAMPLE_CODE
entt::entity entity = m_Registry.create();
m_Registry.emplace<TransformComponent>(entity, glm::mat4(1.0f));
m_Registry.on_construct<TransformComponent>().connect<&OnTransformConstruct>();
if (m_Registry.has<TransformComponent>(entity))
TransformComponent& transform = m_Registry.get<TransformComponent>(entity);
auto view = m_Registry.view<TransformComponent>();
for (auto entity : view)
{
TransformComponent& transform = view.get<TransformComponent>(entity);
}
auto group = m_Registry.group<TransformComponent>(entt::get<MeshComponent>);
for (auto entity : group)
{
auto& [transform, mesh] = group.get<TransformComponent, MeshComponent>(entity);
}
#endif
}
Scene::~Scene()
{
}
entt::entity Scene::CreateEntity()
{
return m_Registry.create();
}
//拿到组件
void Scene::OnUpdate(Timestep ts)
{
//注册组件
auto group = m_Registry.group<TransformComponent>(entt::get<SpriteRendererComponent>);
for (auto entity : group)
{
//拿到对应的组件
auto& [transform, sprite] = group.get<TransformComponent, SpriteRendererComponent>(entity);
Renderer2D::DrawQuad(transform, sprite.Color);
}
}
}