您的位置:首页 > 理论基础 > 计算机网络

cocos2d-X 网络动态下载资源图片

2012-11-16 20:25 513 查看
游戏中经常会把一些资源放在服务器,玩家玩到的时候再动态下载,缓存,显示。

下面介绍下主要实现逻辑。

1.游戏初始化的时候,登陆服务器, 服务器返回一些基本信息,包含外部资源图片的网络地址。

2. 网络请求图片下载

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();

}

3.网络返回图片文件,保存,通知动态加载显示部分--图片下载完成

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());
}

}

4.专门负责动态加载资源的消息监听,并且当接到文件下载完成的消息后,回调显示该图片

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();
}

5.以后再显示该图片,则从本地SD卡缓存中读取文件,有判断方法

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;
}


总结,该逻辑实现后,可以动态加载网络资源,并缓存本地,什么时候加载完成自动显示,并且可以同时进行多张图片的显示缓存,效果很好。

本文出自 “游戏人” 博客,请务必保留此出处http://zgame.blog.51cto.com/6144241/1061850
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: