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庫有利於打包,最好對文件進行加密,加密的內容之後再寫。

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