Palasin itse takaisin C++:n maailmaan ja totesin, että foorumilla on ollut aika hiljaista sen suhteen viime aikoina, jos vertaa esim vuosia taaksepäin. Joten päätimpä nostaa tämän aiheen taas esille, jos joku innostuisi taas koodailemaan jotakin
Aloitin Cocos2D-x:lla uutta projektia, ja kirjastoa tarkemmin tutkaillessani huomasin, että se ei sisällä omaa resurssi manageria, joten päätin tehdä sellaisen itse. Jos joku joskus kyseisellä kirjastolla koodailee peliään ja kiroaa miksi kuvien lataaminen etukäteen on niin vaikeaa / ei halua käyttää aikaa ja päästä helpommalla, niin voit tulla tänne ja kopioida ehkei nopeimman, mutta toimivan resurssi managerin. Manageri pystyy lataamaan tekstuureita PNG-kuvista, musiikkia sekä ääniä. Halutessaan tietenkin tämä on helppo muokata vastaamaan myös jonkin toisen kirjaston tarkoituksia. Muuttaa vain AssetResource structista tekstuurin tyyppiä halutun kirjaston vastaavaksi ja korvaa loadCocos2D-funktion omalla, joka lataa vaikka SDL-surfacen.
Käyttö:
Manageri toimii singletonina ja näin ollen sitä voidaan käyttää missä tahansa kohtaa koodia.
Code: Select all
minioid::ResourceManager::getSingletonPtr()->"TÄHÄN KUTSUTTAVA METODI"
Ennen käyttöä manageri pitää alustaa init()-funktiolla.
Manageri toimii niin, että se lataa resursseja taustalla yhden per frame, joten muista kutsua update()-funktiota aina joka framella. Latauksen päättymisen tiedät, kun isLoading() palauttaa false.
Resursseja lisätään latausjonoon load-funktiolla. HUOM! resurssi EI OLE käytössä heti tämän komennon jälkeen, vaan se lisätään ladattavien resurssien listalle. Voit tarkistaa onko resurssi ladattu isLoaded-funktiolla.
load-funktio tarvitsee myös parametriksi ladattavan resurssin tyypin. (RES_TYPE_TEXTURE, RES_TYPE_SOUND tai RES_TYPE_MUSIC) Kun olet kerran määritellyt resurssin tyypin, niin manageri hoitaa loput itsestään.
Muista vapauttaa ladatut tiedostot remove-komennolla tai vastaavasti voit tyhjentää koko managerin clear-komennolla.
Tässä vielä pieni esimerkki käytöstä:
Code: Select all
minioid::ResourceManager* myResMgr = minioid::ResourceManager::getSingletonPtr();
myResMgr->init();
myResMgr->load("ukkeli.png", minioid::RES_TYPE_TEXTURE);
myResMgr->load("rajahdys.wav", minioid::RES_TYPE_SOUND);
myResMgr->load("musiikki.mp3", minioid::RES_TYPE_MUSIC);
while(1) //MAINLOOP
{
myResMgr.update();
if(myResMgr.isLoading())
{
//Näytetään latausikkuna ja päivitetään vaikka latauspalkkia
}
else
{
//Kaikki on ladattu ja pyöritetään peliä
}
}
EDIT: Parantelin vielä vähän koodia. Lisäsin setResourceFolder nimisen funktion helpottamaan, ettei tarvitse aina kirjoittaa root-kansion nimeä jokaisen resurssin lataukseen. Lisäksi justFinished funktiolla saa tiedon, että kaikki on ladattu valmiiksi kyseisen framen aikana. Tätä voi käyttää, jos tarvitsee vielä alustaa joitakin muuttujia ennen pelin aloittamista.
Sitten vielä itse koodi:
standards.h
Code: Select all
#ifndef CHA_STANDARDS_H
#define CHA_STANDARDS_H
#include <vector>
#include <string>
#include <algorithm>
#endif
ResourceManager.h
Code: Select all
#ifndef CAM_ASS_MGR_H
#define CAM_ASS_MGR_H
#include "standards.h"
#include "cocos2d.h"
#include "SimpleAudioEngine.h"
namespace minioid
{
enum
{
RES_TYPE_TEXTURE = 1,
RES_TYPE_SOUND,
RES_TYPE_MUSIC,
};
struct AssetResource
{
std::string path;
int type;
cocos2d::CCTexture2D* texture;
};
class ResourceManager
{
public:
ResourceManager();
~ResourceManager();
//Use singleton pointer to control the manager. ResourceManager::getSingletonPtr->...
static ResourceManager* getSingletonPtr();
//Init the manager.
void init();
//Updates loading queue. Call this once per frame!
void update();
//Add load request to queue.
//path - relative file path
//resourceType - resource type. (RES_TYPE_TEXTURE) see enum.
void load(std::string path, int resourceType);
//Returns true if file has been already loaded.
//path - relative file path
bool isLoaded(std::string path);
//Removes and unload resource.
void remove(std::string path);
//Clears and unload whole manager.
void clear();
//Returns true if loading isn't completed yet. When false, you know loading is finished.
bool isLoading();
//Returns loading progress as float between 0 and 1. Use this for your progress bar etc.
float getProgressPercent();
//Get loaded texture
//filename - filename of loaded texture
//Warning! Use this method only after current resource is loaded! (you can check isLoaded())
cocos2d::CCTexture2D* getTexture(std::string filename);
//Return true if loading has JUST finished
bool justFinished();
//Set root folder for resources
//Default is "data"
void setResourceFolder(std::string path);
private:
std::string resFolder;
bool justFin;
int totalAssets;
int loadedAssets;
bool isLoadingAssets;
static ResourceManager* singleton_assetMgr;
std::vector<AssetResource> loadingQueue;
std::vector<AssetResource> loadedFiles;
void cocos2DLoad(AssetResource res);
void cocos2DUnload(AssetResource res);
};
}
#endif
ResourceManager.cpp
Code: Select all
#include "ResourceManager.h"
namespace minioid
{
ResourceManager::ResourceManager()
{
}
ResourceManager::~ResourceManager()
{
}
ResourceManager* ResourceManager::singleton_assetMgr;
ResourceManager* ResourceManager::getSingletonPtr()
{
if(!singleton_assetMgr)
{
singleton_assetMgr = new ResourceManager();
}
return singleton_assetMgr;
}
void ResourceManager::init()
{
clear();
loadingQueue.clear();
loadedFiles.clear();
isLoadingAssets = false;
loadedAssets = 0;
totalAssets = 0;
justFin = false;
resFolder = "data";
}
void ResourceManager::update()
{
justFin = false;
if(!loadingQueue.empty())
{
AssetResource pathToLoad = loadingQueue.back();
cocos2DLoad(pathToLoad);
loadingQueue.pop_back();
if(loadingQueue.empty()) justFin = true;
}
loadedAssets = (int)loadedFiles.size();
totalAssets = ((int)loadingQueue.size())+loadedAssets;
if(loadingQueue.empty()) isLoadingAssets = false;
if(!loadingQueue.empty()) isLoadingAssets = true;
}
void ResourceManager::load(std::string path, int resourceType)
{
isLoadingAssets = true;
AssetResource fileToLoad;
fileToLoad.path = path;
fileToLoad.type = resourceType;
loadingQueue.push_back(fileToLoad);
}
bool ResourceManager::isLoaded(std::string path)
{
std::vector<AssetResource>::iterator it;
for(it=loadedFiles.begin(); it < loadedFiles.end(); it++)
{
AssetResource tempRes = *it;
if(path == tempRes.path) return true;
}
return false;
}
void ResourceManager::remove(std::string path)
{
std::vector<AssetResource>::iterator it;
for(it=loadedFiles.begin(); it < loadedFiles.end(); it++)
{
AssetResource tempRes = *it;
if(path == tempRes.path)
{
cocos2DUnload(tempRes);
loadedFiles.erase(it);
}
}
}
void ResourceManager::clear()
{
std::vector<AssetResource>::iterator it;
for(it=loadedFiles.begin(); it < loadedFiles.end(); it++)
{
AssetResource tempRes = *it;
remove(tempRes.path);
}
loadingQueue.clear();
loadedFiles.clear();
}
bool ResourceManager::isLoading()
{
return isLoadingAssets;
}
float ResourceManager::getProgressPercent()
{
if(totalAssets == 0) return 0;
return ((float)loadedAssets)/((float)totalAssets);
}
void ResourceManager::cocos2DLoad(AssetResource res)
{
std::vector<AssetResource>::iterator it;
for(it=loadingQueue.begin(); it<loadingQueue.end(); it++)
{
AssetResource tempRes = *it;
if(tempRes.path == res.path)
{
std::string loadPath = ""+resFolder+"/"+tempRes.path;
if(res.type == RES_TYPE_TEXTURE)
{
cocos2d::CCTexture2D* tex = cocos2d::CCTextureCache::sharedTextureCache()->addImage(loadPath.c_str());
tempRes.texture = tex;
loadedFiles.push_back(tempRes);
break;
}
if(res.type == RES_TYPE_SOUND)
{
CocosDenshion::SimpleAudioEngine::sharedEngine()->preloadEffect(loadPath.c_str());
}
if(res.type == RES_TYPE_MUSIC)
{
CocosDenshion::SimpleAudioEngine::sharedEngine()->preloadBackgroundMusic(loadPath.c_str());
}
}
}
}
void ResourceManager::cocos2DUnload(AssetResource res)
{
if(res.type == RES_TYPE_TEXTURE)
{
cocos2d::CCTextureCache::sharedTextureCache()->removeTexture(res.texture);
}
if(res.type == RES_TYPE_SOUND)
{
CocosDenshion::SimpleAudioEngine::sharedEngine()->unloadEffect(res.path.c_str());
}
}
cocos2d::CCTexture2D* ResourceManager::getTexture(std::string filename)
{
std::vector<AssetResource>::iterator it;
for(it=loadedFiles.begin(); it<loadedFiles.end(); it++)
{
AssetResource tempRes = *it;
if(tempRes.path == filename) return tempRes.texture;
}
return 0;
}
bool ResourceManager::justFinished()
{
return justFin;
}
void ResourceManager::setResourceFolder(std::string path)
{
resFolder = path;
}
}