转自 http://blog.csdn.net/tj_slamdunk/article/details/12016853
这是自己做项目时遇到的,这部分代码是自己在 前辈们的基础上自己在增加了少许代码,让代码更比较完整一些,亲测可用,方便实惠。不多说,上代码,感谢网上的前辈
- 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");
第二个参数是下载完成回调,方便做一些后续处理。。可以加载多张图片,并缓存到本地,代码已做判断本地是否已有该资源并作出相应的操作。。还有一些下载失败,文件验证这些没有加上