zpack使用

来源:互联网 发布:怎么在淘宝上传图片 编辑:程序博客网 时间:2024/06/03 05:30

一、相关说明

在使用cocos2dx开发时,资源需要打包,这里我们使用一个开源项目:zpack项目。

zpack可以把所有资源打成一个包,然后在运行时解析包内的资源即可。

二、资源打包

  • 1.下载zpack项目,用VS打开工程,然后编译项目生成zpEditorD.exe程序。
  • 2.打开zpEditorD创建一个项目,这里我取名叫做data.zpk。
  • 3.然后把Cocos2dx工程下Resources里的资源放到新建的文件夹data目录下。
  • 4.再打开zpEditorD工具栏Edit中的Add Folder添加data文件夹即可。

三、添加库文件

1.把zpack下相关文件资源拷贝到项目的cocos2d\external\下,并且创建了PackManager管理类文件。
这里写图片描述
2.在cocos2d\cocos下的Android.mk文件里的LOCAL_SRC_FILES下添加zpack路径,如下:

../external/zpack/PackManager.cpp \../external/zpack/zpack.cpp \../external/zpack/zpCompressedFile.cpp \../external/zpack/zpFile.cpp \../external/zpack/zpPackage.cpp \../external/zpack/zpWriteFile.cpp \../external/zpack/WriteCompressFile.cpp \

上面是为了Android工程编译时找到库文件,同时在proj.android\jni下的Android.mk导入目录,如:

$(call import-add-path,$(LOCAL_PATH)/../../cocos2d/external/zpack)LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes \                    $(LOCAL_PATH)/../../cocos2d/external \                    $(LOCAL_PATH)/../../cocos2d/external/zpack \

3.然后打开VS工程,在libcocos2d中的external文件夹,添加筛选器zpack,在导入zpack中的所有文件。

四、zpack使用

1.问题处理:

目前zpack文件只能在windows下使用,还需要把一些Android下没有的函数做一些更改,才能在Android下使用。比如_fseeki64函数更改为fseek函数,

void File::seekInPackage(){#if defined(WIN32) && defined(_WINDOWS)    _fseeki64(m_package->m_stream, m_offset + m_readPos, SEEK_SET);    m_package->m_lastSeekFile = this;#else    fseek(m_package->m_stream, m_offset + m_readPos, SEEK_SET);    m_package->m_lastSeekFile = this;#endif}

除此之外,注意zpack定义了宽字符和普通字符,这里我们使用普通字符,即屏蔽掉宽字符,在zpack.h中关闭ZP_USE_WCHAR就行了。

#if defined (_MSC_VER) && defined (UNICODE)//  #define ZP_USE_WCHAR#endif

2.PackManager类编写

PackManager类是我们用来管理zpack的类,
PackManager.h

#ifndef __CPACKMANAGER_H__#define __CPACKMANAGER_H__#include <cocos2d.h>#include "iostream"#include "zpPackage.h"#include "zpack.h"#include "zpFile.h"using namespace std;USING_NS_CC;namespace zp{    class IPackage;}class CPackManager{public:    CPackManager();    ~CPackManager();    bool Open(const std::string& filename, const zp::String& path, bool readonly = false);    unsigned char*  getFileData(const std::string& Path, ssize_t &size);private:    void clear();    void copy();private:    zp::IPackage*   m_pack;    std::string     m_zpkFileName;};CPackManager&  PackManager();#endif

PackManager.cpp文件如下:

#include "PackManager.h"#include <fstream>CPackManager& PackManager(){    static CPackManager s;    return s;}CPackManager::CPackManager()    :m_pack(nullptr),    m_zpkFileName(""){}CPackManager::~CPackManager(){}void CPackManager::clear(){    if (m_pack != NULL)    {        zp::close(m_pack);        m_pack = NULL;    }}bool CPackManager::Open(const std::string& filename ,const zp::String&  path, bool readonly){    clear();    m_zpkFileName = filename;    copy();    std::string writePath = cocos2d::FileUtils::getInstance()->getWritablePath() ;    writePath += m_zpkFileName;    // 这里很奇怪,在Android下就可以 string 直接转化为 wstring,难道是linux的原因    // 其实在这里可以关闭到宽字符,避免麻烦#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID    const zp::String newpath(writePath);#else    zp::String newpath = path;#endif    m_pack = zp::open(newpath.c_str(), readonly ? zp::OPEN_READONLY : 0);    if (m_pack == NULL)    {        return false;    }    return true;}void CPackManager::copy(){    ssize_t  len = 0;    std::string filepath = cocos2d::FileUtils::getInstance()->fullPathForFilename(m_zpkFileName);    unsigned char * data = cocos2d::FileUtils::getInstance()->getFileData(filepath, "r+b", &len);    std::string writePath = cocos2d::FileUtils::getInstance()->getWritablePath();    writePath += m_zpkFileName;    FILE* fp = fopen(writePath.c_str(), "w+");    if (fp == nullptr)    {        return;    }    fwrite(data, sizeof(unsigned char), len, fp);    fclose(fp);    if (len > 0 && data)    {        delete[] data;        data = nullptr;    }}/* *   getFileData函数需要在 CCFileUtilsAndroid类中使用 */unsigned char*  CPackManager::getFileData(const std::string& Path, ssize_t &size){    std::stringstream ss;    ss << "data/";    ss << Path;    zp::IReadFile* file = nullptr;#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID    file = m_pack->openFile(ss.str().c_str());#endif    if (file == NULL)    {        return  nullptr;    }    unsigned char* buffer = new unsigned char[file->size() + 1];    size = file->read((zp::u8*)buffer, file->size());    buffer[file->size()] = '\0';    return buffer;}

3.修改CCFileUtilsAndroid类

在Android平台下,使用资源如添加精灵都要经过CCFileUtilsAndroid类,所以需要 通过CCFileUtilsAndroid读取data.zpk文件中的内容。
CCFileUtilsAndroid中有两个函数需要修改一下:

Data FileUtilsAndroid::getData(const std::string& filename, bool forString)unsigned char* FileUtilsAndroid::getFileData(const std::string& filename, const char* mode, ssize_t * size)

在getData函数中需要修改的部分是,当找到assets/data.zpk时,即调用CPackManager::getFileData函数,返回读取的数据

    if (fullPath[0] != '/')    {        if (fullPath.find("assets/") == std::string::npos && filename.find("data.zpk") == std::string::npos)        {            data = PackManager().getFileData(filename, size);        }        else        {            ......

getFileData函数修改同上:

    if (fullPath[0] != '/')    {        if(filename.find("data.zpk") == std::string::npos &&  fullPath.find("assets/") == std::string::npos)        {            data = PackManager().getFileData(filename, *size);        }        else        {            ......

最后在AppDelegate.cpp添加查找路径

    std::string writePath = cocos2d::FileUtils::getInstance()->getWritablePath();    std::vector<std::string> searchPaths;#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID    searchPaths.push_back("data");    searchPaths.push_back(writePath);#else    searchPaths.push_back(writePath);    searchPaths.push_back("../../Resources");    searchPaths.push_back(writePath + "/Resources");#endif    CCFileUtils::getInstance()->setSearchPaths(searchPaths);

在第一个使用的场景中使用即可

    zp::String filename = _T("data.zpk");    PackManager().Open("data.zpk" , filename );

五、总结

使用zpack库有利于打包,最好对文件进行加密,加密的内容之后再写。

原创粉丝点击