zoukankan      html  css  js  c++  java
  • [游戏] 游戏中的资源管理资源高速缓存

    来源: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有额外时间的时候可以把未来可能用到的资源载入到资源高速缓存。
        最后,尽管在游戏的资源管理中资源打包不是必须的,但仍然建议大家把资源文件按类型分别打包到单一的文件中,这将为你节省磁盘空间,并加快游戏的载入速度。

  • 相关阅读:
    第五课:数字门构造
    出一道题 : 证明 牛顿迭代法
    网友 水登江河 说
    出现 杨辉三角 的 一些 场合
    泰勒级数 无敌 逼近法
    出一道题 : 证明 ln | sec x + tan x | =
    从 角动量守恒 推导出 椭圆轨道
    三角函数 版 的 霍奇猜想
    傅里叶级数 和 高次多项式函数
    实际上, 物空必能 先生 的 一些 观点 可能 是 正确 的
  • 原文地址:https://www.cnblogs.com/hcbin/p/1743663.html
Copyright © 2011-2022 走看看