[游戏] - 游戏中的资源管理----资源高速缓存

来源:http://www.cppblog.com/Leaf/archive/2009/05/17/83230.html

 

《游戏中的资源管理――资源高速缓存》
转载请注明出处:http://groups.google.com/group/jianguhan


1.什么是资源高速缓存
    资源高速缓存的原理与其它内存高速缓存的工作原理是相似的。在游戏的状态转换过程中,有些数据是刚才使用过的,那么直接从资源高速缓存中载入即可。例如,RPG­游戏中主角从大地图进入一个房间,探索一番后主角退出房间,此时只要直接从缓存中载入大地图数据即可,节省了从硬盘载入数据的时间,要知道从硬盘载入数据是非常­慢的。当然,如果你的游戏所使用的数据文件很少,那么你可以在游戏运行过程中把这些数据完全储存在内存中,而不使用资源高速缓存。

 


2.一个简单的资源高速缓存管理器
    下面我将向你展示一个比较简单的资源高速缓存管理器,源代码来自我上一个游戏,如果你需要知道更多关于资源高速缓存方面的知识,请参考<<Game Coding Complete>>的第八章。
首先,需要一个机制来唯一标识一个资源,我们用下面这个结构来做资源句柄:

 

 
   
struct ResHandle
{
ResHandle(std::
string & resName, void * buffer, int size)
{
m_resName
= resName;
m_size
= size;
m_buffer
= buffer;
}


~ ResHandle()
{
if (m_buffer != 0 ) delete[] m_buffer;
}


std::
string m_resName; // 资源名
void * m_buffer; // 资源句柄所标识的资源
DWORD m_size; // 资源所占内存大小  
};

好了,现在我们可以从资源名来找出这个资源了,接下来实现这个资源高速缓存管理器:

 

 

 
   
class CacheManager
{
public :
CacheManager();
~ CacheManager();

// 载入资源,resName为资源名,若载入成功size被设为该资源的大小
// 注意,管理中的资源不能在管理器外用delete显示的删除它
void * Load(std:: string resName, DWORD * size = 0 );
// 设置缓存大小,单位MB
void SetCacheSize( int sizeMB) { m_cacheSize = sizeMB * 1024 * 1024 ; }
// 得到缓存大小,单位MB
int GetCacheSize() { return m_cacheSize / 1024 / 1024 ; }


private :
void Free(); // 释放lru链表中最后一个资源
void * Update(ResHandle * res); // 更新lru链表
ResHandle * Find(std:: string & resName); // 找出该资源名的资源句柄

private :
DWORD m_cacheSize;
// 缓存大小
DWORD m_allocated; // 已使用的缓存大小


// lru链表,记录最近被使用过的资源
std::list < ResHandle *> m_lru;
// 资源标识映射
std::map < std:: string , ResHandle *> m_resources;
};


CacheManager:: CacheManager ()
{
m_cacheSize
= 0 ;
m_allocated
= 0 ;
}


CacheManager::
~ CacheManager ()
{
while ( ! m_lru.empty()) Free(); // 释放所有管理中的资源
}


void * CacheManager::Load(std:: string resName, DWORD * size)
{
ResHandle
* handle = Find(resName); // 查找该资源是否在缓存中

if (handle != 0 ) // 如果找到该资源句柄,则返回该资源并更新lru链表
{
if (size != 0 ) * size = handle -> m_size;
return Update(handle);
}
else
{
// 先检测资源大小
DWORD _size = 资源大小;


// 是否有足够空间?
while (_size > (m_cacheSize - m_allocated))
{
if (m_lru.empty()) break ;
Free();
}
m_allocated
+= _size;


buffer
= new char [_size];
// 在这里用任何你能想到的办法载入资源文件到 buffer




// 记录当前资源
ResHandle * handle = new ResHandle(resName, buffer, _size);
m_lru.push_front(handle);
m_resources[resName]
= handle;

if (size != 0 ) * size = _size;
return buffer;
}

return 0 ;
}


void CacheManager::Free()
{
std::list
< ResHandle *> ::iterator gonner = m_lru.end();
gonner
-- ;
ResHandle
* handle = * gonner;
m_lru.pop_back();
m_resources.erase(handle
-> m_resName);
m_allocated
-= handle -> m_size;
delete handle;
}


void * CacheManager::Update(ResHandle * res)
{
m_lru.remove(res);
m_lru.push_front(res);
m_size
= res -> m_size;
return res -> m_buffer;
}

ResHandle
* CacheManager::Find(std:: string & resName)
{
std::map
< std:: string , ResHandle *> ::iterator it = m_resources.find(resName);
if (it == m_resources.end()) return 0 ;
return ( * it).second;
}

 

 

至此,你已经可以在游戏中缓存任何你想缓存的资源了^_^

 

3. 资源管理进阶
    至此你已经可以在游戏中缓存任何你想缓存的资源了,但是你的任务还没完成,当你请求的资源存在于缓存之外时,那个闪耀的硬盘灯可能就是玩家最感兴趣的东西了。
因此你必须根据不同的游戏类型使用不同的载入方式: 
    一次载入所有东西:适用于任何以界面或关卡切换的游戏 
    只在关键点载入资源:很多射击游戏都使用这样的设计,如“半条命” 
    持续载入:适用于开放型地图的游戏,如“侠盗猎车手”
    如果有可能的话,你还可以使用缓存预测机制,当CPU有额外时间的时候可以把未来可能用到的资源载入到资源高速缓存。
    最后,尽管在游戏的资源管理中资源打包不是必须的,但仍然建议大家把资源文件按类型分别打包到单一的文件中,这将为你节省磁盘空间,并加快游戏的载入速度。

转载于:https://www.cnblogs.com/hcbin/archive/2010/05/25/1743663.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值