我寫過一個2d遊戲。寫2d遊戲時大部分的精力花在gui的撰寫和寫腳本的接口上了。之前寫gui的時候,new一個button的時候就load一個texture,如果頻繁切換gui,texture就會頻繁地load和release。
所以把紋理的加載管理與gui寫在一塊是很浪費效率的。最好的方法是紋理的加載與釋放與gui無關。
感謝飯中淹教會了我這個思路:給紋理設置一個重要度,初始值1,當有gui使用到這個紋理的時候,每幀都增加這個紋理的重要度,當沒有任何程序使用這個紋理的時候,每幀減少紋理的重要度,當重要度減少到0以下,就釋放這個紋理。
這樣做的好處是,經常調用的紋理在內存中的時間比較長,這樣程序調用紋理時很容易命中。而且可以讓多個gui調用同一個紋理。
以下是代碼。我用hge的,所以調用紋理的函數是hge的函數。(*^__^*) 嘻嘻……
存儲紋理用的是數組,但是用哈希表會更好。(*^__^*) 嘻嘻……
使用方法:
先調用Init()初始化
然後要用紋理的時候:
HTEXTURE = kResourceSystem::Instance().GetTexture("aaa.bmp");
釋放紋理的時候:
kResourceSystem::Instance().ThrowTexture("aaa.bmp");
每幀便忘了在主循環函數裏調用
kResourceSystem::Instance().Upadate();
- #pragma once
- #include "hge.h"
- #include "Singleton.h"
- #define MAXRESOURCENUM 200
- struct sResourceList
- {
- char* FileName;
- HTEXTURE tex;
- int Importance;//重要度
- int iRendered;//記錄有幾處引用
- sResourceList(){
- FileName = NULL;
- tex = NULL;
- Importance = 0;
- iRendered = 0;
- }
- };
- class kResourceSystem:public Pattern::Singleton<kResourceSystem>
- {
- public:
- kResourceSystem(){;}
- ~kResourceSystem();
- void Init(HGE* Hge){hge = Hge;}
- HTEXTURE GetTexture(const char* FileName);//從列表中返回一個紋理
- void ThrowTexture(const char* FileName);//通知有一個紋理在某處不用了
- void ThrowTexture(HTEXTURE tex);
- void Update();//邏輯更新
- protected:
- private:
- sResourceList m_list[MAXRESOURCENUM];
- HTEXTURE CreateTexture(const char* FileName);//新建一個紋理
- void ReleaseTexture(int index);//釋放紋理
- int GetIndex(const char* FileName);//返回紋理在數組中的位置
- HGE* hge;
- };
- #include "ResourceSystem.h"
- #include "iostream"
- using namespace std;
- int kResourceSystem::GetIndex(const char *FileName)
- {
- for (int i = 0;i < MAXRESOURCENUM;i++)
- {
- if (m_list[i].FileName != NULL)
- {
- //cout << "第" << i << "個元素是:" << m_list[i].FileName << endl;
- if (strcmp(m_list[i].FileName,FileName) == 0)
- {
- //cout << FileName << "與第" << i << "個元素匹配!" << endl;
- return i;
- }
- }
- }
- return -1;
- }
- HTEXTURE kResourceSystem::GetTexture(const char *FileName)
- {
- //cout << "GetTexture:" << FileName << endl;
- int nTemp;
- nTemp = GetIndex(FileName);
- if (nTemp == -1)
- {
- return CreateTexture(FileName);
- }
- else
- {
- m_list[nTemp].iRendered++;
- return m_list[nTemp].tex;
- }
- return NULL;
- }
- void kResourceSystem::ThrowTexture(const char* FileName)
- {
- //printf("ThrowTexture,調用函數%s文件的%u行/n",__FILE__,__LINE__);
- int nTemp;
- nTemp = GetIndex(FileName);
- if (nTemp == -1)
- {
- return;
- }
- else{
- m_list[nTemp].iRendered--;
- if (m_list[nTemp].iRendered < 0)
- {
- m_list[nTemp].iRendered = 0;
- }
- }
- }
- void kResourceSystem::ReleaseTexture(int index)
- {
- //printf("ReleaseTexture,調用函數%s文件的%u行/n",__FILE__,__LINE__);
- printf("ReleaseTexture:釋放文件名:%s/n",m_list[index].FileName);
- if (m_list[index].tex)
- {
- hge->Texture_Free(m_list[index].tex);
- m_list[index].tex = NULL;
- }
- delete [] m_list[index].FileName;
- m_list[index].FileName = NULL;
- m_list[index].iRendered = 0;
- m_list[index].Importance = 0;
- }
- HTEXTURE kResourceSystem::CreateTexture(const char* FileName)
- {
- //printf("CreateTexture,調用函數%s文件的%u行",__FILE__,__LINE__);
- for (int i = 0;i < MAXRESOURCENUM;i++)
- {
- if (m_list[i].FileName == NULL)
- {
- m_list[i].FileName = new char[256];
- strcpy(m_list[i].FileName,FileName);
- m_list[i].tex = hge->Texture_Load(FileName);
- m_list[i].Importance = 1;
- m_list[i].iRendered = 1;
- return m_list[i].tex;
- break;
- }
- }
- return NULL;
- }
- void kResourceSystem::Update()
- {
- for (int i = 0;i < MAXRESOURCENUM;i++)
- {
- if (m_list[i].iRendered <= 0 && m_list[i].FileName !=NULL)
- {
- m_list[i].Importance--;
- if (m_list[i].Importance <= 0)
- {
- ReleaseTexture(i);
- }
- }
- else if(m_list[i].iRendered > 0 && m_list[i].FileName != NULL)
- {
- m_list[i].Importance++;
- }
- }
- }
- void kResourceSystem::ThrowTexture(HTEXTURE tex)
- {
- //printf("ThrowTexture,調用函數%s文件的%u行/n",__FILE__,__LINE__);
- for (int i = 0;i < MAXRESOURCENUM;i++)
- {
- if (m_list[i].tex == tex)
- {
- m_list[i].iRendered--;
- //cout << "第" << i << "個元素,iRendered = " << m_list[i].iRendered << endl;
- return;
- break;
- }
- }
- }
- kResourceSystem::~kResourceSystem()
- {
- /*for (int i = 0;i < MAXRESOURCENUM;i++)
- {
- if (m_list[i].FileName != NULL)
- {
- ReleaseTexture(i);
- }
- }*/
- }