c++ - 实体组件系统 - 组件相互需要

标签 c++ entity software-design entity-system entity-component-system

我已经为我的游戏 (C++) 编写了一个实体组件系统。然后我重构了我的渲染系统以使用 Entities/RenderComponents 而不是一些虚拟的可绘制接口(interface)。他们是一些类,我认为强制他们成为一个组件没有太大意义。其中一个类是 map 。

我的 map 类由一个平铺地形类和一些其他数据(不重要)组成。平铺地形类以(目前)TiledTerrainLayer 类的形式管理多个图层。在重构渲染系统之前,我简单地继承了DrawableTransformable,让这个类可以被渲染系统绘制。现在要求它是一个实体,至少有一个 TransformComponent 和一些 RenderComponent

现在,TiledTerrainLayerRenderComponent 应该只拥有顶点和纹理的引用,也许还有一个标志,表明它是否已经创建。 TiledTerrainComponent 将拥有图 block 索引列表以及图 block 和 map 大小。

现在我的问题是,当我设置一个图 block 时(使用类似 SetTile(size_t tileIndex, const Position & pos) 方法),我还必须更新顶点数组的纹理坐标。

我通常可以接受一个组件需要另一个组件。例如,SpriteRenderComponent 需要一个 TransformComponent,我也同意一个组件访问另一个组件的信息。例如。 GetBoundingBox() 方法使用变换组件的位置。

我想避免的是两个组件相互“交叉引用”,就像 TiledTerrainComponent (TTC) 和 TiledTerrainRenderComponent 的情况一样。 (TTRC)(TTRC 获取 TTC 的 tileIndexList 以创建自己,并且 TTC 在调用其 SetTile() 方法时调用 TTRC 的 UpdateVertices() 方法。

最后,我知道组件应该主要是数据。我只添加了直接获取或修改该数据的方法,例如 SetTile() 或 GetTexture()。在上述情况下,系统是否可行?如果可行,它会是什么样子?

最佳答案

听起来你只需要一个 Dirty Flag .

当您更改 Tiled Terrain 上的图 block 索引、大小或其他属性时,您不会立即调用 Tiled Renderer 来更新其顶点(毕竟,您可能还有许 multimap block 更新尚未到达此帧 - 它可能是每次都重新计算顶点很浪​​费)

相反,Tiled Terrain 渲染器只是将其内部 hasBeenModifiedSinceLastUse 标志设置为 true。它根本不需要了解渲染器。

接下来,当在绘制之前更新您的 Tiled Renderer 时,您让它询问它的 Tiled Terrain 自上次绘制以来它是否已经更新(如果您想要定位更改,您甚至可以查询更新列表)。如果是这样,您可以批量更新顶点,以获得更好的代码和数据局部性。

在此过程中,您重置修改后的标志,以便如果后续帧没有更新,您可以按原样重新使用最后生成的一组顶点。

现在你的依赖点只有一种方式——渲染器依赖于瓦片数据,但瓦片数据除了维护它的标志之外不知道渲染。

关于c++ - 实体组件系统 - 组件相互需要,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49177579/

相关文章:

c++ - 如何将抽象类的派生类作为参数传递?

php - 流体接口(interface)如何返回 $this 和值?

spring - 为什么在使用 Spring OpenEntityManagerInViewFilter 时会出现 JPA LazyInitializationException?

java - 关于工厂方法模式的澄清

php - 使用服务层在我的分层应用程序中向哪里抛出异常?

c++ - 为什么我的程序会因大值而不是小值而导致程序崩溃?

c++ - unordered_map 中带有模板类的 C2535(Microsoft Visual Studio 2015 CTP6)

c++ - 编译标志 -static 对于 gcc 真正意味着什么

java - JPA:结果列表 - 将 Object[] 转换为元组

c# - 使用 Entity Framework 检查mysql中是否存在数据