我为我的游戏编写了一个实体组件系统(C ++)。然后我重构了我的渲染系统以使用Entities / RenderComponents而不是一些虚拟可绘制界面。他们是一些课程,我不认为强迫他们成为一个组成部分是非常有意义的。其中一个类是地图。
我的地图类包含平铺地形类和其他一些数据(不重要)。平铺地形类以({1}}类的(目前)形式管理多个层。在重构渲染系统之前,我只是从TiledTerrainLayer
和Drawable
继承,以使渲染系统能够绘制该类。现在,它必须是一个至少有Transformable
和一些TransformComponent
的实体。
现在,RenderComponent
应该只拥有顶点和纹理的引用,也许还有一个标志,表明它是否已经创建。然后,TiledTerrainLayerRenderComponent
将拥有磁贴内容列表以及磁贴和地图大小。
现在我的问题是,当我设置一个图块(使用像TiledTerrainComponent
方法之类的东西时,我还必须更新顶点数组的纹理坐标。
对于需要其他组件的一个组件,我一般都很好。例如,SetTile(size_t tileIndex, const Position & pos)
需要SpriteRenderComponent
,我也可以使用一个组件访问另一个组件的信息。例如。 GetBoundingBox()方法使用转换组件的位置。
我想要避免的是两个组件,即交叉引用'彼此就像TransformComponent
(TTC)和TiledTerrainComponent
一样。 (TTRC)(TTRC获取TTC的tileIndexList来创建自己,并且TTC在调用其SetTile()方法时调用TTRC的UpdateVertices()方法。
最后,我知道组件应该主要是数据。我只添加了直接获取或修改数据的方法,如SetTile()或GetTexture()。在上述情况下系统是否可行,如果是,它会是什么样子?
答案 0 :(得分:2)
听起来你需要的只是Dirty Flag。
当你在Tiled Terrain上更改tile索引,大小或其他属性时,你不会立即通过Tiled渲染器来更新它的顶点(毕竟,你可能还有许多tile更新来到这个框架 - 它可能是每次浪费重新计算你的顶点)
相反,Tiled Terrain渲染器只是将其内部hasBeenModifiedSinceLastUse
标志设置为true。它根本不需要知道渲染器。
接下来,在绘图之前更新Tiled渲染器时,您可以询问其Tiled Terrain自上次绘制以来是否已更新(如果您想要定位更改,您甚至可以查询更新列表)。如果是这样,您可以在一个大批量中更新顶点,以获得更好的代码和数据位置。
在此过程中,您重置修改后的标志,以便在后续帧中没有更新时,您可以按原样重复使用上一组生成的顶点。
现在您的依赖关系只指向一种方式 - 渲染器依赖于平铺数据,但平铺数据除了保持其标志外不知道渲染。