cocos2d-x 网络下载图片

本文介绍使用cocos2d-x进行网络图片下载的实践,通过CImageDownloader类发送HTTP请求,下载图片并回调加载完成后的处理。代码包括检查本地资源是否存在并进行相应操作,支持多张图片下载。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这是自己做项目时遇到的,这部分代码是自己在 前辈们的基础上自己在增加了少许代码,让代码更比较完整一些,亲测可用,方便实惠。不多说,上代码,感谢网上的前辈

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.youkuaiyun.com/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");


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





评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值