(纹理)资源系统的设计

时间:2018-08-25 12:50:18

标签: c++ 2d textures sprite resource-management

对于一个开源游戏,我想重新设计资源管理系统,但是陷入了僵局,需要一些指向一些阅读材料或现在去哪里的指针。

(大多)起点是LoaderHeader / Src

资源格式:

  • 资源(通常)在归档文件中,该文件由编号文件(无名称)组成,可以是任何类型,并且可以包含相关的元数据(大小,绘制偏移量...)
  • 通常是常用格式(wav,midi,bmp),但可以使用自定义格式,例如对于纹理:
    • 2D偏移(模型矩阵转换)
    • 播放器彩色蒙版(超灰度bmp)
    • 分区的bmp(例如,链接(索引)到身体和头部(bmp)以在同一文件中重复使用bmp)
  • 可能的扩展名/覆盖:具有2个相同名称的存档(不同的文件夹)将合并它们(较晚加载的存档条目添加或覆盖较早的存档条目)

我要解决的问题是凌乱的代码(没有SRP ...),资源的不统一处理以及大多数访问的dynamic_cast(基本上是dynamic_cast<type*>(Get("foo", 42)))。仅使用一种纹理也可以简化渲染(也许是2种:一种带有播放器蒙版,一种没有播放器蒙版)

我的方法(基于ENTT):

  • ResourceLocator:给定名称,返回要加载的档案列表(处理扩展名/覆盖)
  • ResourceCache<Type>:保存给定类型的已加载资源
  • ResourceLoader<Type>:加载资源
  • ResourceRegistry:可容纳多个缓存,1个定位符和(也许)装载程序。通过首先检查缓存并在未命中时加载它(将其添加到缓存)来提供对所有资源的访问权限

这对于声音效果和音乐很有效:

SoundEffect& get(ResId id){
   if(id in soundcache) return it;
   archive& = get(id.name);
   SoundEffect* effect = load(archive)
   add to cache and return effect;
}

这很好,很通用。但是我正在努力为具有不同类型的纹理执行此操作:

  • “普通”纹理(背景,按钮...)->简单
  • 特定于地图的纹理(例如,取决于地图类型,有积雪或无积雪的树木。以前,Loader存储了对地图档案的引用,而简称为GetMapTexture(idx)->的使用者可能不是是否需要所有地图,我是否应该在更改地图时卸载所有地图并根据需要重新加载?
  • 特定于国家的纹理(每个国家都有档案和/或档案中的偏移量)->使用("archive", number)作为键不再起作用。

另外可能需要组合许多纹理(例如,分割位图或带有建筑物/人物的阴影...),并且有动画。这导致fixed size multi-D-arrays具有许多不同的索引,其含义包含在Loader类中。

因此“常规”纹理很容易:只需将它们加载到OGL纹理中并使用即可。其他的(通常)需要将多个图像组合成1个纹理。因此,我不想将这些部分放到纹理缓存中,而只将它们合并。但是拥有这些多重D阵列也感觉像是设计缺陷。我将如何引用/使用它们?别人怎么做?

注意:组成纹理/ bld ...的图像的索引可以很容易地根据国家/地区索引,建筑物索引,动画帧索引...来计算。

用法示例(来自当前/旧代码):

drawAnimal(int type, int dir, int animationFrame){animal_cache[type][dir][animationFrame].draw(pos...);} drawCarrier(...){carrier_cache[carriedWare][dir][animationFrame][isFat].draw(pos, playerColor,...);} drawBuilding(...){building_cache[nationIdx][bldIdx].draw(pos, playerColor,...);}

0 个答案:

没有答案