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");
第二个参数是下载完成回调,方便做一些后续处理。。可以加载多张图片,并缓存到本地,代码已做判断本地是否已有该资源并作出相应的操作。。还有一些下载失败,文件验证这些没有加上