Войти
ПрограммированиеСтатьиОбщее

Использование контейнеров в разработке игр. (2 стр)

Автор:

Карты ресурсов

Поговорим о картах ресурсов. Карты нужны для доступа к информации по определенному ключу. Когда мы имеем дело с игровыми ресурсами, то обычно таким ключом является имя файла, в котором этот ресурс хранится. Слишком часто один и тот же ресурс используется совместно с множеством других ресурсов. Яркий тому пример - текстуры. Одна и та же текстура может использоваться в нескольких моделях. Следовательно, нет смысла для каждой из моделей загружать отдельный экземпляр текстуры. Поэтому имеет смысл для загрузки ресурса обращаться к карте. Карта работает следующим образом. Проверяет, загружен ли уже такой ресурс. Если нет, то загружает его. Если да, то возвращает уже загруженный ресурс.

Для реализации такой карты будем использовать класс std::map из библиотеки стандартных классов STL:

template <class Type>
class obj_list { 
public: 
         typedef Type obj_type;       // тип объекта
         typedef Type * ref_type;     // указатель на объект
         typedef map<string, ref_type> obj_map;        // карта
private: 
         obj_map m_map;   // здесь мы храним указатели на загруженные ресурсы
         string m_base_dir;          // корневой каталог

Следующая функция ищет ресурс, если таковой имеется в карте по его имени. Именем в данном случае является имя файла. Если ничего не найдено возвращается NULL.

ref_type find(string & name){ 
         obj_map::iterator i; 
         i = m_map.find(name); 
         if(i==m_map.end()) return NULL; 
         return ((*i).second); 
}; 

Соответственно загружать ресурс нужно только тогда, когда find() возвращает NULL:

ref_type load(string & filename){ 
        ref_type o = find(filename); 
        if(o==NULL) { 
                o = new Type(); 
                if(!o->load(m_base_dir + "\\" + filename)){ 
                        delete o; 
                        o = NULL; 
                } 
                m_map.insert(obj_map::value_type(filename, o)); 
        } 
        return o; 
}; 

Не забываем удалить все загруженные ресурсы перед удалением карты:

void clear(void) { 
        obj_map::iterator i; 
        for(i = m_map.begin(); i!=m_map.end(); i++){ 
                ref_type o = (*i).second; 
                delete o; 
        } 
        m_map.clear(); 
}; 

Полностью код obj_list можно найти в obj_list.h.

Напоследок рассмотрим вариант использования карты ресурсов на примере загрузки текстур. Итак, объявляем класс-обертку для текстуры (далее пояснения идут в комментариях к классу):

class texture { 
private: 
        bool m_valid;  // загружена ли текстура
        LPDIRECT3DTEXTURE8 m_pTexture; // указатель на текстуру
public: 
        texture(void){ 
                m_valid = false; // изначально текстура не инициализирована
                m_pTexture = NULL; 
        } 
        ~texture(void){ 
                if(m_pTexture!=NULL) 
                        m_pTexture->Release();  // освобождаем COM интерфейс текстуры
        } 
        bool load(string & filename){  // здесь мы грузим тектуру из файла
                if(!m_valid) { 
                        if(FAILED(D3DXCreateTextureFromFile( 
                                  g_pd3dDevice, filename.c_str(), &m_pTexture ))) {
                                m_pTexture = NULL;
                        }else {
                                m_valid = true;
                        }
                } 
                return m_valid; 
        } 
        bool valid(void) { return m_valid; };  // загружена ли текстура
        LPDIRECT3DTEXTURE8  get() { 
                return m_pTexture;   // функия возвращает указатель на текстуру
        };
};.

Теперь можно объявить карту для текстур и глобальную переменную - глобальная карта текстур:

typedef obj_list<texture > texture_list;
texture_list g_TextureList;

Код загрузки текстуры очень прост:

texture   *pMyTexture = g_TextureList.load("MYFILE.DDS");

Страницы: 1 2

#STL, #итераторы, #контейнеры

14 июня 2002 (Обновление: 17 сен. 2009)

Комментарии [6]