游戏中经常会把一些资源放在服务器,玩家玩到的时候再动态下载,缓存,显示。
下面介绍下主要实现逻辑。
1.游戏初始化的时候,登陆服务器, 服务器返回一些基本信息,包含外部资源图片的网络地址。
2. 网络请求图片下载
3.网络返回图片文件,保存,通知动态加载显示部分--图片下载完成
- void HttpDownload::onMenuPostBinaryTestClicked(cocos2d::CCObject *sender , char * setUrl_ , char * childpath , char * filename)
- {
- CCHttpRequest* request = new CCHttpRequest();
- if (this->container)
- {
- this->observerID = CCImageNotificationCenter::sharedNotificationCenter()->addObserver(filename,container,useMask);
- }
- std::string url_ = "";
- url_ += setUrl_;
- url_+=childpath;
- url_+= filename;
- this->filename_ = filename;
- request->setUrl(url_.c_str());
- request->setRequestType(CCHttpRequest::kHttpGet);
- request->setResponseCallback(this, callfuncND_selector(HttpDownload::onHttpRequestCompleted));
- request->setTag("GET PIC");
- CCHttpClient::getInstance()->send(request);
- request->release();
- }
4.专门负责动态加载资源的消息监听,并且当接到文件下载完成的消息后,回调显示该图片
- void HttpDownload::onHttpRequestCompleted(cocos2d::CCNode *sender, void *data)
- CCHttpResponse *response = (CCHttpResponse*)data;
- 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()->getWriteablePath();
- 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);
- //传入container的下载请求会添加侦听,待下载完毕自动添加到container上
- if (this->container)
- {
- // container 是一个CCLayer ,用来显示动态加载的资源
- CCImageNotificationCenter::sharedNotificationCenter()->postNotification(this->observerID.getCString());
- }
- }
5.以后再显示该图片,则从本地SD卡缓存中读取文件,有判断方法
- CCString CCImageNotificationCenter::addObserver(const char *imageName,CCLayer* layer,bool useMask)
- {
- CCString* observerIDstr = CCString::createWithFormat("%d",m_observerID);
- m_notificationCenter.addObserver(this, callfuncO_selector(CCImageNotificationCenter::imageLoaded), observerIDstr->getCString(), new imgstruct(imageName, observerIDstr->getCString(), layer, 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(imgstruct* img)
- {
- CCLOG("imageLoaded success,imageName:%s",img->imageName.c_str());
- CCSprite* sprite = GOEUtilies::getSpriteFromWriteablePath(img->imageName.c_str());
- CCLOG("got sprite 0x%X", sprite);
- if (img->useMask)
- {
- img->layer->addChild(GOEUtilies::createMaskedSprite(sprite,"mask.png"));
- }
- else{
- float scale_ = (float) img->layer->getContentSize().width / (float)sprite->getContentSize().width;
- sprite->setAnchorPoint(ccp(0,0));
- sprite->setScale( scale_ );
- img->layer->addChild(sprite);
- }
- this->removeObserver(img->observerId.c_str());
- img->release();
- }
- CCSprite* GOEUtilies::getSpriteFromWriteablePath(const char* name){
- std::string path = CCFileUtils::sharedFileUtils()->getWriteablePath();
- 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("50black.png");//加载资源并非图片时返回的默认图
- }
- CCSprite* sprite = CCSprite::createWithTexture(texture);
- texture->release();
- return sprite;
- }
总结,该逻辑实现后,可以动态加载网络资源,并缓存本地,什么时候加载完成自动显示,并且可以同时进行多张图片的显示缓存,效果很好。