zoukankan      html  css  js  c++  java
  • cocos2d-x 制作资源下载页面

    开发游戏中用到从http 服务器下载文件的操作,所以要有个界面显示下载进度,同时联网采用curl库,因为下载是同步的操作,所以用了多线程

    啥也不说,直接贴代码。我是采用ccbi做的页面,你也可以做一个标准的CCLayer,然后添加一个进度条的CCSprite。

    ////////////////////////////DownLoadScene.h/////////////////////////

    #include "cocos2d.h"

    #include "cocos-ext.h"

    #include "jsoncpp.h"

    #include "curl.h"

    #include "pthread.h" 

    USING_NS_CC;

    USING_NS_CC_EXT;

    class DownLoadScene :publicCCLayer, publicCCBSelectorResolver, publicCCBMemberVariableAssigner,publicCCNodeLoaderListener

    {

    public:

        CREATE_FUNC(DownLoadScene);

    public:

        

        virtual bool init();

        virtual void onEnter();

        virtual void onExit();

        virtual ~DownLoadScene()

        {

            CC_SAFE_RELEASE_NULL(m_pSprite);

        }

        //CCBSelectorResolver

        virtual SEL_MenuHandler onResolveCCBCCMenuItemSelector(CCObject * pTarget, const char* pSelectorName);

        virtual SEL_CallFuncN onResolveCCBCCCallFuncSelector(CCObject * pTarget, const char* pSelectorName) { return NULL; };

        virtual SEL_CCControlHandler onResolveCCBCCControlSelector(CCObject * pTarget, const char* pSelectorName);

        //CCBMemberVariableAssigner

        virtual bool onAssignCCBMemberVariable(CCObject* pTarget, const char* pMemberVariableName, CCNode* pNode);

        virtual bool onAssignCCBCustomProperty(CCObject* pTarget, const char* pMemberVariableName, CCBValue* pCCBValue) { return false; };

        

        void onNodeLoaded(cocos2d::CCNode *pNode, cocos2d::extension::CCNodeLoader *pNodeLoader);

        void onHttpReqFinished(CCHttpClient* client, CCHttpResponse* response);

      

    private:

     

        CCSprite    *m_pSprite;//进度条的CCSprite,注意锚点要设置为0,0.5,方便我们做进度显示

        void onTimer(float t);//进度条刷新函数

        pthread_t pid;//由于curl下载是同步操作,无法更新,所以要加一个线程来显示

        static void* updateInfo(void *r);//线程函数

    };


    class DownLoadSceneLoader : public CCLayerLoader{

    public:

        CCB_STATIC_NEW_AUTORELEASE_OBJECT_METHOD( DownLoadSceneLoader, loader );

        

        CCB_VIRTUAL_NEW_AUTORELEASE_CREATECCNODE_METHOD( DownLoadScene);

    };

    ////////////////////////////DownLoadScene.cpp/////////////////////////


     //

    //  DownLoadScene.cpp

    //

    //  Created by Leo on 13-9-12.

    //

    //


    #include "DownLoadScene.h"

    FILE           *s_pfileWrite;//下载时写文件的指针

    CURL        *s_pCurl;//curl库

    int             s_iFileSize;//总文件大小

    int             s_iCurrentFileSize;//当前下载大小

    CCSprite    *s_pSpriteLoading;//进度条的CCSprite的外部指针

    int         s_iSpriteWidth;//进度条的宽度保存

    boolDownLoadScene::init()

    {

        //////////////////////////////

        // 1. super init first

        if ( !CCLayer::init() )

        {

            returnfalse;

        }

        returntrue;

    }

    voidDownLoadScene::onEnter()

    {

        

        CCLayer::onEnter();

        

    }

    voidDownLoadScene::onExit()

    {

        CCLayer::onExit();

    }


    SEL_MenuHandler DownLoadScene::onResolveCCBCCMenuItemSelector(CCObject * pTarget, const char* pSelectorName)

    {

        

        returnNULL;

    }

    SEL_CCControlHandler DownLoadScene::onResolveCCBCCControlSelector(CCObject * pTarget, const char* pSelectorName)

    {

        returnNULL;

    }



    bool DownLoadScene::onAssignCCBMemberVariable(CCObject* pTarget, const char* pMemberVariableName, CCNode* pNode)

    {

    //这里是CCB的处理,如果没有用cocosbuilder做的界面可以忽略

        CCB_MEMBERVARIABLEASSIGNER_GLUE(this, "progress", CCSprite*, m_pSprite);

        returnfalse;

    }

    //处理头信息,注意curl是一条一条的头信息发过来的,我们只关心里面的Content-Length获取总文件大小并保存到s_iFileSize中

    size_t DownLoadHeadCallBack( char *ptr, size_t size,size_t nmemb, void *stream)

    {

        char buff[512] = {0};

        string pketword = "Content-Length: ";

        int i = 0;

        

        if(NULL == ptr)

        {

            printf("packet read error! ");

            return size * nmemb;

        }

        while((ptr[i] == pketword[i])&&(ptr[i] != ' '))

        {

            i++;

        }

        if(ptr[i] == pketword[i])

        {

            //sscanf( (char*)ptr, "%*s%[^ ]", buff );//%s遇空格停止,加*则是忽略第一个读到的字符串

            sscanf((char*)ptr, "%*[^ ] %[^ ]", buff);//第一段到空格结束前的内容都忽略掉,第二段从空格开始换行结束

            CCLog("Size=%s ",buff);

            s_iFileSize = atoi(buff);

            return size * nmemb;

        }

        else

        {

            return size * nmemb;

        }

    }

    //写入文件操作,同时记录当前写的大小

    size_t DownLoadWriteCallBack(void *ptr, size_t size, size_t nmemb, void *stream)

    {

        int written = fwrite(ptr, size, nmemb, (FILE *)s_pfileWrite);

        CCLog("size download=%ld",size*nmemb);

        s_iCurrentFileSize+=size*nmemb;

        CCLog("test = %d  %f",s_iSpriteWidth,(float)((float)s_iCurrentFileSize/(float)s_iFileSize));

        s_pSpriteLoading->setTextureRect(CCRectMake(0, 0, s_iSpriteWidth*(float)((float)s_iCurrentFileSize/(float)s_iFileSize), s_pSpriteLoading->getContentSize().height));

        return written;

    }

    //刷新进度条,这里用切割Texture的方式做的进度显示

    void DownLoadScene::onTimer(float t)

    {

            CCLog("size download=%d",s_iCurrentFileSize);

            CCLog("test = %d  %f",s_iSpriteWidth,(float)((float)s_iCurrentFileSize/(float)s_iFileSize));

            s_pSpriteLoading->setTextureRect(CCRectMake(0, 0, s_iSpriteWidth*(float)((float)s_iCurrentFileSize/(float)s_iFileSize), s_pSpriteLoading->getContentSize().height));

    }

    //线程函数,联网下载文件,用http的post方式请求

    void* DownLoadScene::updateInfo(void* args){

        s_pCurl = curl_easy_init();

        if (!s_pCurl)

            return NULL;

        

        Json::Value root;

        Json::FastWriter writer;

        root["bv"]=true;

    //设置文件下载路径

        std::string pszPath = CCFileUtils::sharedFileUtils()->getWritablePath()+"data.zip";

        if((s_pfileWrite=fopen(pszPath.c_str(),"w+"))==NULL)

        {

            curl_easy_cleanup(s_pCurl);

            exit(1);

        }

        std::string rUrl = URL_PARSE;

        rUrl+="/v/dup";//设置url

        curl_easy_setopt(s_pCurl, CURLOPT_TIMEOUT, 10);//设置超时时间

        curl_easy_setopt(s_pCurl, CURLOPT_POSTFIELDS, writer.write(root).c_str());//设置post数据

        curl_easy_setopt(s_pCurl, CURLOPT_URL, rUrl.c_str());//设置URL

        curl_easy_setopt(s_pCurl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);//设置URL的版本

        curl_easy_setopt(s_pCurl, CURLOPT_WRITEDATA, &s_pfileWrite);//设置写数据的文件指针

        curl_easy_setopt(s_pCurl, CURLOPT_WRITEHEADER,NULL);//设置写头文件的指针,这里要设置为NULL,否则有问题

        curl_easy_setopt(s_pCurl, CURLOPT_WRITEFUNCTION, DownLoadWriteCallBack);//设置数据写回调

        curl_easy_setopt(s_pCurl, CURLOPT_HEADERFUNCTION, DownLoadHeadCallBack);//设置头数据写回调

        curl_easy_setopt(s_pCurl, CURLOPT_VERBOSE, true);//打开联网log,发布的时候可以关闭

        curl_easy_perform(s_pCurl);//联网请求,会停留在这里直到完成

        curl_easy_cleanup(s_pCurl);//关闭CURL

        fclose(s_pfileWrite);//关闭文件句柄

        curl_global_cleanup();//清除curl

        returnNULL;

    }

    voidDownLoadScene::onNodeLoaded(cocos2d::CCNode *pNode, cocos2d::extension::CCNodeLoader *pNodeLoader)

    {

        s_iCurrentFileSize =0;

        s_iFileSize=1;

        s_pSpriteLoading = m_pSprite;

        s_iSpriteWidth = s_pSpriteLoading->getContentSize().width;

        schedule(schedule_selector(DownLoadScene::onTimer), 1);

        m_pSprite->setTextureRect(CCRectMake(0, 0, m_pSprite->getContentSize().width*(s_iCurrentFileSize/s_iFileSize), m_pSprite->getContentSize().height));

        

        pthread_create(&pid,NULL,updateInfo,NULL); //开启新线程

        

        

    }


  • 相关阅读:
    配置基于全局地址池的DHCP
    配置基于接口地址池的DHCP
    将access数据库导入mysql
    php读取数据库数据,出现中文乱码(数据库中没有出现乱码)
    mysql 错误1054
    sublimetext3 安装php语法检测
    各种幻灯片特效SuperSlide
    jquery特效网
    生成loading图片
    iScroll内部textarea滑动不了bug
  • 原文地址:https://www.cnblogs.com/riskyer/p/3318098.html
Copyright © 2011-2022 走看看