zpack使用

一、相关说明

在使用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库有利于打包,最好对文件进行加密,加密的内容之后再写。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章