本文TextureCache类异步加载功能的代码抽出,总共代码就200多行,感兴趣可以看看。
研究这个主要是因为项目中需要异步插入数据,但之前的方法在AndroID上总是崩溃所以想到TextureCache有异步加载的功能就将其抽出了。
原文地址:http://blog.csdn.net/qqmcy/article/details/39890837
代码下载:http://download.csdn.net/detail/qqmcy/8011589
首先,创建AsyncTasktime类,主要模拟一个费时的方法
AsyncTasktime.h
#include "cocos2d.h"USING_NS_CC;class AsyncTasktime{public: //模拟一个费时 *** 作 bool initWithImagefileThreadSafe(const std::string &filename); };
AsyncTasktime.cpp
//// AsyncTasktime.cpp// cpp4//// Created by 杜甲 on 10/8/14.////#include "AsyncTasktime.h"bool AsyncTasktime::initWithImagefileThreadSafe(const std::string &filename){ std::this_thread::sleep_for(std::chrono::milliseconds(3000)); return true;}
创建异步加载功能类
asynctest.h
//// asynctest.h// cpp4//// Created by 杜甲 on 10/8/14.////#ifndef __cpp4__asynctest__#define __cpp4__asynctest__#include "cocos2d.h"#include "AsyncTasktime.h"using namespace std;USING_NS_CC;class asynctest : public Ref{public: CREATE_FUNC(asynctest); virtual bool init(); asynctest(); // 异步加载 voID addImageAsync(const string &path,const function<voID(AsyncTasktime *)> &callback);private: voID addImageAsyncCallback(float dt); //加载数据 voID loadImage(); public: struct AsyncStruct { public: AsyncStruct(const string &fn,function<voID(AsyncTasktime *)> f): filename(fn),callback(f){}; string filename; function<voID(AsyncTasktime *)> callback; }; protected: typedef struct { AsyncStruct *asyncStruct; AsyncTasktime *image; }ImageInfo; thread *_loadingThread; queue<AsyncStruct *> *_asyncStructQueue; deque<ImageInfo *> *_ImageInfoQueue; mutex _asyncStructQueueMutex; mutex _imageInfoMutex; mutex _sleepMutex; condition_variable _sleepCondition; bool _needQuit; int _asyncRefCount; unordered_map<std::string,AsyncTasktime* > _textures; };#endif /* defined(__cpp4__asynctest__) */
asynctest.cpp
//// asynctest.cpp// cpp4//// Created by 杜甲 on 10/8/14.////#include "asynctest.h"asynctest::asynctest(): _loadingThread(nullptr),_asyncStructQueue(nullptr),_ImageInfoQueue(nullptr),_needQuit(false),_asyncRefCount(0){ }bool asynctest::init(){ return true;}voID asynctest::addImageAsync(const string &path,const function<voID (AsyncTasktime *)> &callback){ AsyncTasktime *texture = nullptr; auto it = _textures.find(path); if (it != _textures.end()) { texture = it->second; } if (texture != nullptr) { callback(texture); return; } if (_asyncStructQueue == nullptr) { _asyncStructQueue = new queue<AsyncStruct *>(); _ImageInfoQueue = new deque<ImageInfo *>(); _loadingThread = new thread(&asynctest::loadImage,this); _needQuit = false; } if (0 == _asyncRefCount) { Director::getInstance()->getScheduler()->schedule(schedule_selector(asynctest::addImageAsyncCallback),this,false); } ++_asyncRefCount; auto data = new AsyncStruct(path,callback); _asyncStructQueueMutex.lock(); _asyncStructQueue->push(data); _asyncStructQueueMutex.unlock(); _sleepCondition.notify_one(); //将等待 condition_variable 对象的其中一个线程解除阻塞。 }voID asynctest::loadImage(){ AsyncStruct *asyncStruct = nullptr; while (true) { queue<AsyncStruct *> *pQueue = _asyncStructQueue; _asyncStructQueueMutex.lock(); if (pQueue->empty()) { } else{ asyncStruct = pQueue->front(); pQueue->pop(); _asyncStructQueueMutex.unlock(); } AsyncTasktime *image = nullptr; bool generateImage = false; auto it = _textures.find(asyncStruct->filename); if (it == _textures.end()) { _imageInfoMutex.lock(); ImageInfo *imageInfo; size_t pos = 0; size_t infoSize = _ImageInfoQueue->size(); for (; pos < infoSize; pos++) { imageInfo = (*_ImageInfoQueue)[pos]; if (imageInfo->asyncStruct->filename.compare(asyncStruct->filename) == 0) break; } _imageInfoMutex.unlock(); if (infoSize == 0 || pos == infoSize) generateImage = true; } if (generateImage) { const string &filename = asyncStruct->filename; image = new AsyncTasktime(); if (image && !image->initWithImagefileThreadSafe(filename)) { continue; } } auto imageInfo = new ImageInfo(); imageInfo->asyncStruct = asyncStruct; imageInfo->image = image; _imageInfoMutex.lock(); _ImageInfoQueue->push_back(imageInfo); _imageInfoMutex.unlock(); } if (_asyncStructQueue != nullptr) { delete _asyncStructQueue; _asyncStructQueue = nullptr; delete _ImageInfoQueue; _ImageInfoQueue = nullptr; } }voID asynctest::addImageAsyncCallback(float dt){ deque<ImageInfo *> *imagesQueue = _ImageInfoQueue; _imageInfoMutex.lock(); if (imagesQueue->empty()) { _imageInfoMutex.unlock(); } else{ auto imageInfo = imagesQueue->front(); imagesQueue->pop_front(); _imageInfoMutex.unlock(); auto asyncStruct = imageInfo->asyncStruct; auto image = imageInfo->image; if (asyncStruct->callback) { asyncStruct->callback(image); } --_asyncRefCount; if (0 == _asyncRefCount) { Director::getInstance()->getScheduler()->unschedule(schedule_selector(asynctest::addImageAsyncCallback),this); } }}
调用:
HelloWorldScene.h
#ifndef __HELLOWORLD_SCENE_H__#define __HELLOWORLD_SCENE_H__#include "cocos2d.h"#include "asynctest.h"USING_NS_CC;class HelloWorld : public cocos2d::Layer{public: // Here's a difference. Method 'init' in cocos2d-x returns bool,instead of returning 'ID' in cocos2d-iphone HelloWorld(); virtual bool init(); // there's no 'ID' in cpp,so we recommend returning the class instance pointer static cocos2d::Scene* scene(); // implement the "static node()" method manually CREATE_FUNC(HelloWorld); private: Size winSize; //这里添加一个回调方法 voID loadCallback1(AsyncTasktime *time); };#endif // __HELLOWORLD_SCENE_H__
HelloWorldScene.cpp
// on "init" you need to initialize your instancebool HelloWorld::init(){ ////////////////////////////// // 1. super init first if ( !Layer::init() ) { return false; } auto as = asynctest::create(); as->retain(); as->addImageAsync("test",CC_CALLBACK_1(HelloWorld::loadCallback1,this)); return true;}voID HelloWorld::loadCallback1(AsyncTasktime *time){ log("加载完成"); }
控制台:
cocos2d: 加载完成
这样我们就将TextureCache中
virtual voID addImageAsync(conststd::string &filepath,const std::function<voID(Texture2D*)>& callback);
这个异步加载数据的功能实现了。 总结以上是内存溢出为你收集整理的Cocos2d-x3.2 TextureCache类异步加载功能讲解全部内容,希望文章能够帮你解决Cocos2d-x3.2 TextureCache类异步加载功能讲解所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)