</pre> 工具功能;</p><p> 把琐碎的图片合并到一个文件中,减小文件的体积,同时在使用文件的时候减少io操作,并使用zlib进行压缩</p><p> 实现原理</p><p> 索引文件夹下面的所有资源,按规则依次写入一个文件中,并压缩</p><p> 文件格式:</p><p> 文件格式分为3块:</p><p><pre name="code" class="cpp">第一块为头文件信息,只写一次
typedef struct _ccpFileInfo
{
uint32_t version;
uint32_t fileCount;//所有文件数量
}ccpFileInfo;
第二块为索引文件信息,数量为fileCount
typedef struct _ccpDataInfo
{
char name[KFILENAME_LEN];//文件的名字 ui/aa/bb
uint64_t offset;//在文件中的开始位置
uint64_t size;
char md5[KMD5_LEN];//md5码
_ccpDataInfo(){}
_ccpDataInfo(const char *name,uint64_t offset,uint64_t size,const char*md5){
strcpy(this->name, name);
this->offset = offset;
this->size = size;
strcpy(this->md5, md5);
}
}ccpDataInfo;
第三块为文件信息,数量也为fileCount
同时在项目中需要一个解析器来解压缩文件,并加载到内存中,以下方法就是把zip解压到documents
//expand zip to documents
void MFPCache::expand(const char *zipFile){
std::string fromPath = FileUtils::getInstance()->fullPathForFilename(zipFile);
std::string toPath = FileUtils::getInstance()->getWritablePath();
std::string newFileName= ReplaceString(zipFile, ".zip", "");
std::string newFilePath= toPath +"/"+newFileName;
//exist
if (0 == access(newFilePath.c_str(), 0)) {
//alread exist
}else{
assert(unCompress(newFilePath.c_str(), fromPath.c_str()));
}
//open it,only read
m_bFd =fopen(newFilePath.c_str(), "r");
if(m_bFd){
//index file
ccpFileInfo fileInfo;
memset(&fileInfo, 0, KCCP_FILEINFO_LEN);
fread(&fileInfo, KCCP_FILEINFO_LEN, 1, m_bFd);
for (int i=0; i < fileInfo.fileCount; ++i) {
ccpDataInfo data;
fread(&data, KCCP_DATAINFO_LEN, 1, m_bFd);
m_dataMap.insert(std::make_pair(data.name, data));
}
}else{
assert(m_bFd);
}
}
把图片加入到内存中
void MFPCache::addImage(const char *file){
// npc/1.png 50702 23801075 aaa
uint64_t size = 0;
unsigned char *data = (unsigned char *)this->getBlockData(file,&size);
if (data !=nullptr) {
Image *image = new Image();
image->initWithImageData((unsigned char*)data, size);
Director::getInstance()->getTextureCache()->addImage(image, file);
CC_SAFE_DELETE(image);
}else{
assert(0);
}
}
把plist和图片同时加入到内存中,这里需要把SpriteFrameCache中的addSpriteFramesWithDictionary方法改成publish的
void MFPCache::addPlist(const char *file){
std::string png = ReplaceString(file, ".plist", ".png");
ValueMap map;
uint64_t size = 0;
char *data = this->getBlockData(file,&size);
parseXml(data,size,map);
addImage(png.c_str());
Texture2D *texture= Director::getInstance()->getTextureCache()->getTextureForKey(png);
SpriteFrameCache::getInstance()->addSpriteFramesWithDictionary(map,texture);
}
有了这些方法,在游戏中的调用就是
<span style="white-space:pre"> </span>MFPCache::getInstance()->expand("data.bin.zip");
MFPCache::getInstance()->addPlist("ui.plist");
Sprite *spr1 = Sprite::createWithSpriteFrameName("ui/+30s.png");
spr1->setPosition(Point(100,100));
addChild(spr1);
MFPCache::getInstance()->addImage("ken.png");
Sprite *spr2 = Sprite::create("ken.png");
spr2->setPosition(Point(200,200));