2014年9月4日 星期四

cocos2d-x 网络下载图片

http://www.58player.com/blog-2537-95426.html

  这是自己做项目时遇到的,这部分代码是自己在 前辈们的基础上自己在增加了少许代码,让代码更比较完整一些,亲测可用,方便实惠。不多说,上代码,感谢网上的前辈 
         
        CImageDownload.h
        
        class CImageDownloader : public cocos2d::CCObject
        {
        
        public:
        
         virtual bool init();
        
         void SendHttpRequest(CCObject* pTarget, SEL_ImageNotification pSelector, const char* url, CCNode* node, const char* filename);
         void HttpRequestComplete(cocos2d::extension::CCHttpClient *sender, cocos2d::extension::CCHttpResponse *response);
        
         CREATE_FUNC(CImageDownloader);
        public:
         //观察者ID
         CCString    observerID;
         //下载的图片加载到当前layer层上
         CCNode*    node;
         //是否使用遮罩
         bool        useMask;
         //图片文件名
         const char* filename;
        }; 
         
        CImageDownload.cpp
        
        bool CImageDownloader::init()
        {
         useMask = false;
         return true;
        }
        
        void CImageDownloader::SendHttpRequest(CCObject* pTarget, SEL_ImageNotification pSelector, const char* url, CCNode* node, const char* filename)
        {
         std::string path = CCFileUtils::sharedFileUtils()->getWritablePath();
         path += filename;
         if (CCFileUtils::sharedFileUtils()->isFileExist(CCFileUtils::sharedFileUtils()->fullPathForFilename(path.c_str())))
         {
         CCSprite* spr = CCSprite::create(path.c_str());
         node->addChild(spr);
         return;
         }
        
         CCHttpRequest* request = new CCHttpRequest();
         this->node = node;
         this->filename = filename;
         if (this->node)
         {
         this->observerID = CCImageNotificationCenter::sharedImageNotificationCenter()->addObserver(filename,node,useMask);
         }
         request->setUrl(url);
         request->setRequestType(CCHttpRequest::kHttpGet);
         request->setResponseCallback(this, httpresponse_selector(CImageDownloader::HttpRequestComplete));
         CCImageNotificationCenter::sharedImageNotificationCenter()->m_ImageNotificationTarget = pTarget;
         CCImageNotificationCenter::sharedImageNotificationCenter()->m_pImageNotificationSelector = pSelector;
         request->setTag("GET IMAGE");
         CCHttpClient::getInstance()->send(request);
         request->release();
        }
        
        void CImageDownloader::HttpRequestComplete(CCHttpClient *sender, CCHttpResponse *response)
        {
         if (!response)
         {
         return;
         }
        
         // You can get original request type from: response->request->reqType
         if (0 != strlen(response->getHttpRequest()->getTag()))
         {
         CCLog("%s completed", response->getHttpRequest()->getTag());
         }
        
         int statusCode = response->getResponseCode();
         char statusString[64] = {};
         sprintf(statusString, "HTTP Status Code: %d, tag = %s", statusCode, response->getHttpRequest()->getTag());
         CCLog("response code: %d", statusCode);
        
         if (!response->isSucceed())
         {
         CCLog("response failed");
         CCLog("error buffer: %s", response->getErrorBuffer());
         return;
         }
        
         // dump data
         std::vector<char> *buffer = response->getResponseData();
         std::string path = CCFileUtils::sharedFileUtils()->getWritablePath();
         std::string bufffff(buffer->begin(),buffer->end());
        
         //保存到本地文件
         path += this->filename;
         CCLOG("path: %s",path.c_str());
         FILE *fp = fopen(path.c_str(), "wb+");
         fwrite(bufffff.c_str(), 1,buffer->size(), fp);
         fclose(fp);
        
         //传入node的下载请求会添加侦听,待下载完毕自动添加到node上
         if (this->node)
         {
         // node 是一个CCLayer ,用来显示动态加载的资源
         CCImageNotificationCenter::sharedImageNotificationCenter()->postNotification(this->observerID.getCString(), NULL);
         }
        } 
         
        CImageNotificationCenter.h
        
        typedef void (CCObject::*SEL_ImageNotification)();
        #define imagenotification_selector(_SELECTOR) (SEL_ImageNotification)(&_SELECTOR)
        
        //图片结构
        class imgstruct : public CCObject
        {
        public:
         imgstruct(const char* iName, const char* idStr, CCNode* node, bool mask)
         {
         imageName = std::string(iName);
         observerId = std::string(idStr);
         this->node = node;
         useMask = mask;
         }
         ~imgstruct()
         {
         }
        
         std::string imageName;
         std::string observerId;
         CCNode* node;
         //是否使用遮罩
         bool useMask;
        };
        
        //图片监听,下载完成触发
        class CCImageNotificationCenter : public CCNotificationCenter
        {
        public:
         static CCImageNotificationCenter* sharedImageNotificationCenter(void);
        
         CCString addObserver(const char *imageName,CCNode* node,bool useMask);
         void imageLoaded();
         void removeObserver(const char *name);
        
         void postNotification(const char *name, CCObject *object);
        
         void imageLoaded(CCObject *obj);
        
         static CCSprite* getSpriteFromWriteablePath(const char* name);
         //创建遮罩sprite
         static CCSprite* createMaskedSprite(CCSprite* src, const char* maskFile);
        public:
         CCObject* m_ImageNotificationTarget;
         SEL_ImageNotification m_pImageNotificationSelector;
        private:
         CCNotificationCenter        m_notificationCenter;
         int                         m_observerID;
        }; 
         
        CImageNotificationCenter.cpp
        
        CCImageNotificationCenter* CCImageNotificationCenter::sharedImageNotificationCenter( void )
        {
         static CCImageNotificationCenter imageNotificationCenter;
         return &imageNotificationCenter;
        }
        
        CCString CCImageNotificationCenter::addObserver(const char *imageName, CCNode* node, bool useMask)
        {
         CCString* observerIDstr =  CCString::createWithFormat("%d",m_observerID);
        
         m_notificationCenter.addObserver(this, callfuncO_selector(CCImageNotificationCenter::imageLoaded), observerIDstr->getCString(), 
         new imgstruct(imageName, observerIDstr->getCString(), node, useMask));
        
         m_observerID++;
         return observerIDstr->getCString();
        }
        
        void CCImageNotificationCenter::removeObserver(const char *name)
        {
         m_notificationCenter.removeObserver(this, name);
        }
        
        void CCImageNotificationCenter::postNotification(const char *name, CCObject *object)
        {
         m_notificationCenter.postNotification(name, object);
        }
        
        void CCImageNotificationCenter::imageLoaded(CCObject *obj)
        {
         imgstruct* img = (imgstruct*)obj;
         CCLOG("imageLoaded success,imageName:%s",img->imageName.c_str());
         CCSprite* sprite = CCImageNotificationCenter::getSpriteFromWriteablePath(img->imageName.c_str());
         CCLOG("got sprite 0x%X", sprite);
         if (img->useMask)
         {
         img->node->addChild(CCImageNotificationCenter::createMaskedSprite(sprite,"mask.png"));
         }
         else
         {
         float scale_ = (float) img->node->getContentSize().width  / (float)sprite->getContentSize().width;
         sprite->setAnchorPoint(ccp(0.5f,0.5f));
         //sprite->setScale(0.5f);
         img->node->addChild(sprite);
         }
         this->removeObserver(img->observerId.c_str());
         img->release();
        
         (m_ImageNotificationTarget->*m_pImageNotificationSelector)();
        }
        
        
        CCSprite* CCImageNotificationCenter::getSpriteFromWriteablePath(const char* name)
        {
         std::string path = CCFileUtils::sharedFileUtils()->getWritablePath();
         path += name;
         FILE* fp = fopen(path.c_str(),"rb");
         if (!fp)
         {
         return NULL;
         }
         fseek(fp,0,SEEK_END);
         int len = ftell(fp);
         fseek(fp,0,SEEK_SET);
         char* buf = (char*)malloc(len);
         fread(buf,len,1,fp);
         fclose(fp);
         CCImage* img = new CCImage;
         img->initWithImageData(buf,len);
         free(buf);
         cocos2d::CCTexture2D* texture = new cocos2d::CCTexture2D();
         bool isImg = texture->initWithImage(img);
         img->release();
         if (!isImg)
         {
         delete texture;
         return CCSprite::create("default.png");//加载资源并非图片时返回的默认图
         }
         CCSprite* sprite = CCSprite::createWithTexture(texture);
         texture->release();
         return sprite;
        }
        
        CCSprite* CCImageNotificationCenter::createMaskedSprite( CCSprite* src, const char* maskFile )
        {
         //创建遮罩 讲的还不错原理参考://http://blog.csdn.net/azymq/article/details/11110019
        
         CCSprite * mask = CCSprite::create(maskFile);
        
         assert(src);
         assert(mask);
        
         CCSize srcContent = src->getContentSize();
         CCSize maskContent = mask->getContentSize();
        
         CCRenderTexture * rt = CCRenderTexture::create(srcContent.width, srcContent.height, kTexture2DPixelFormat_RGBA8888);
        
         float ratiow = srcContent.width / maskContent.width;
         float ratioh = srcContent.height / maskContent.height;
         mask->setScaleX(ratiow);
         mask->setScaleY(ratioh);
        
         mask->setPosition(ccp(srcContent.width / 2, srcContent.height / 2));
         src->setPosition(ccp(srcContent.width / 2, srcContent.height / 2));
        
         ccBlendFunc blendFunc2 = { GL_ONE, GL_ZERO };
         mask->setBlendFunc(blendFunc2);
         ccBlendFunc blendFunc3 = { GL_DST_ALPHA, GL_ZERO };
         src->setBlendFunc(blendFunc3);
        
         rt->begin();
         mask->visit();
         src->visit();
         rt->end();
        
         CCSprite * retval = CCSprite::createWithTexture(rt->getSprite()->getTexture());
         retval->setFlipY(true);
        
         return retval; 
        } 
         
        调用就比较简单了,直接 
         
        const char* url_item = "http://st1.tingall.com/UserData/HeadPics/465247/0.jpg36x36.jpg"; CImageDownloader* item = CImageDownloader::create(); item->SendHttpRequest(this, imagenotification_selector(CBagInterface::loadCompleteCallBack), url_item, rootNode, "item.jpg");  
          
        第二个参数是下载完成回调,方便做一些后续处理。。可以加载多张图片,并缓存到本地,代码已做判断本地是否已有该资源并作出相应的操作。。还有一些下载失败,文件验证这些没有加上