【Cocos2d-x 3.x】 精灵帧缓存和纹理缓存
来源:互联网 发布:淘宝企业店铺的优势 编辑:程序博客网 时间:2024/05/17 02:54
转自泰然网(Cocos2d-x 3.x官方文档):精灵帧缓存:http://www.tairan.com/archives/6378/ 纹理缓存: http://www.tairan.com/archives/6432/
精灵帧缓存
简介
SpriteFrameCache 主要服务于多张碎图合并出来的纹理图片。这种纹理在一张大图中包含了多张小图,直接通过TextureCache引用会有诸多不便,因而衍生出来精灵框帧的处理方式,即把截取好的纹理信息保存在一个精灵框帧内,精灵通过切换不同的框帧来显示出不同的图案。
SpriteFrameCache
SpriteFrameCache的内部封装了一个Map _spriteFrames对象。key为帧的名称。SpriteFrameCache一般用来处理plist文件(这个文件指定了每个独立的精灵在这张“大图”里面的位置和大小),该文件对应一张包含多个精灵的大图,plist文件可以使用TexturePacker制作。
SpriteFrameCache的常用接口和TextureCache类似,不再赘述了,唯一需要注意的是添加精灵帧的配套文件一个plist文件和一张大的纹理图。下面列举了SpriteFrameCache常用的方法:
SpriteFrameCache* cache = SpriteFrameCache::getInstance();
销毁SpriteFrameCache对象:
SpriteFrameCache::destroyInstance();
使用SpriteFrameCache获取指定的精灵帧,创建精灵对象:
SpriteFrameCache *frameCache = SpriteFrameCache::getInstance();frameCache->addSpriteFramesWithFile("boy.plist","boy.png");//boy.png里集合了boy1.png,boy2.png这些小图auto frame_sp = Sprite::createWithSpriteFrameName("boy1.png");//从SpriteFrameCache缓存中找到boy1.png这张图片.this->addChild(frame_sp,2);
SpriteFrameCache vs. TextureCache
SpriteFrameCache精灵框帧缓存。顾名思义,这里缓存的是精灵帧SpriteFrame,它主要服务于多张碎图合并出来的纹理图片。这种纹理在一张大图中包含了多张小图,直接通过TextureCache引用会有诸多不便,因而衍生出来精灵框帧的处理方式,即把截取好的纹理信息保存在一个精灵框帧内,精灵通过切换不同的框帧来显示出不同的图案。
跟TextureCache功能一样,将SpriteFrame缓存起来,在下次使用的时候直接去取。不过跟TextureCache不同的是,如果内存池中不存在要查找的图片,它会提示找不到,而不会去本地加载图片。
- TextureCache时最底层也是最有效的纹理缓存,缓存的是加载到内存中的纹理资源,也就是图片资源。
- SpriteFrameCache精灵框帧缓存,缓存的时精灵帧。
- SpriteFrameCache是基于TextureCache上的封装。缓存的是精灵帧,是纹理指定区域的矩形块。各精灵帧都在同一纹理中,通过切换不同的框帧来显示出不同的图案。
纹理缓存
在游戏中需要加载大量的纹理图片,这些操作都是很耗内存和资源的。
当游戏中有个界面用到的图片非常多,第一次点进这界面时速度非常慢(因为要加载绘制很多图片)出现卡顿,我们可以使用TextureCache提前异步加载纹理,等加载结束,进入到这个界面再使用这些图片速度就会非常快。
Texture2D: 纹理,即图片加载入内存后供CPU和GPU操作的贴图对象。
TextureCache(纹理缓存),用于加载和管理纹理。一旦纹理加载完成,下次使用时可使用它返回之前加载的纹理,从而减少对GPU和CPU内存的占用。
常用的方法
当你创建一个精灵,你一般会使用Sprite::create(pszFileName)。假如你去看Sprite::create(pszFileName)的实现方式,你将看到它将这个图片增加到纹理缓存中去了:
Sprite* Sprite::create(const std::string& filename){ Sprite *sprite = new Sprite(); if (sprite && sprite->initWithFile(filename)) { sprite->autorelease(); return sprite; } _SAFE_DELETE(sprite); return nullptr;}bool Sprite::initWithFile(const std::string& filename){ ASSERT(filename.size()>0, "Invalid filename for sprite"); Texture2D *texture = Director::getInstance()->getTextureCache()->addImage(filename); if (texture) { Rect rect = Rect::ZERO; rect.size = texture->getContentSize(); return initWithTexture(texture, rect); } // don't release here. // when load texture failed, it's better to get a "transparent" sprite then a crashed program // this->release(); return false;}
上面代码显示在控制加载纹理。一旦这个纹理被加载了,在下一时刻就会返回之前加载的纹理引用,并且减少加载的时候瞬间增加的内存。
获取TextureCache
在3.0版本中,TextureCache不再作为单例模式使用。作为Director的成员变量,通过以下方式获取:
Director::getInstance()->getTextureCache();
获取纹理
如果文件名以前没有被加载时,它会创建一个新的Texture2D 对象,它会返回它。它将使用文件名作为key否则,它会返回一个引用先前加载的图像。
TextureCache屏蔽了加载纹理的许多细节;
addImage函数会返回一个纹理Texture2D的引用,如果纹理不存在,则新创建一个,否则返回之前已经存在的:
Texture2D *texture = Director::getInstance()->getTextureCache()->addImage(filename);
也可以通过getTextureForKey方法来获得这个key所对应的纹理缓存,如果这个Key对应的纹理不存在,那么就返回NULL:
Texture2D *texture = Director::getInstance()->getTextureCache()->getTextureForKey(textureKeyName);
异步加载纹理
TextureCache类还支持异步加载资源的功能,利用addImageAsync方法。你可以很方面地给addImageAsync方法添加一个回调方法,这样,当纹理异步加载结束的时候,可以得到通知。
你可以选择异步加载方式,这样你就可以为loading场景增加一个进度条。关键代码如下:
TextureCacheTest::TextureCacheTest(): _numberOfSprites(20), _numberOfLoadedSprites(0){ auto size = Director::getInstance()->getWinSize(); _labelLoading = Label::createWithTTF("loading...", "fonts/arial.ttf", 15); _labelPercent = Label::createWithTTF("%0", "fonts/arial.ttf", 15); _labelLoading->setPosition(Point(size.width / 2, size.height / 2 - 20)); _labelPercent->setPosition(Point(size.width / 2, size.height / 2 + 20)); this->addChild(_labelLoading); this->addChild(_labelPercent); // load textrues Director::getInstance()->getTextureCache()->addImageAsync("Images/HelloWorld.png", _CALLBACK_1(TextureCacheTest::loadingCallBack, this)); Director::getInstance()->getTextureCache()->addImageAsync("Images/grossini.png", _CALLBACK_1(TextureCacheTest::loadingCallBack, this)); Director::getInstance()->getTextureCache()->addImageAsync("Images/grossini_dance_01.png", _CALLBACK_1(TextureCacheTest::loadingCallBack, this)); ....}void TextureCacheTest::loadingCallBack(cocos2d::Texture2D *texture){ ++_numberOfLoadedSprites; char tmp[10]; sprintf(tmp,"%%%d", (int)(((float)_numberOfLoadedSprites / _numberOfSprites) * 100)); _labelPercent->setString(tmp); if (_numberOfLoadedSprites == _numberOfSprites) { this->removeChild(_labelLoading, true); this->removeChild(_labelPercent, true); addSprite(); }}
清理缓存
removeUnusedTextures则会释放当前所有引用计数为1的纹理,即目前没有被使用的纹理。比如新场景创建好后,使用此方法释放没有使用的纹理非常方便:
Director::getInstance()->getTextureCache()->removeUnusedTextures();
当没有其它对象(比如sprite)持有纹理的引用的时候,纹理仍然会存在内存之间。基于这一点,我们可以立马从缓存中移除出去,这样,当纹理不存需要的时候,马上就会从内存中释放掉。如下代码所示:
Director::getInstance()->getTextureCache()->removeTextureForKey("Images/grossinis_sister2.png");
当收到"Memory Warning"时,可以调用removeAllTextures()方法。在短期内: 它还将释放一些资源,防止您的应用程序被杀害; 中期: 它将分配更多的资源;从长远来看:它会是相同的:
Director::getInstance()->getTextureCache()->removeAllTextures();
- 【Cocos2d-x 3.x】 精灵帧缓存和纹理缓存
- Cocos2d-x3.x 精灵帧缓存和纹理缓存
- cocos2d-x利用精灵表和纹理缓存实现优化
- cocos2d 3.x 纹理缓存
- 我的Cocos2d-x学习笔记(七)纹理缓存、帧缓存、精灵的创建、zOrder
- cocos2d-x中缓存帧精灵创建
- cocos2d-x 3.0纹理缓存
- [Cocos2d-x v3.x官方文档]精灵帧缓存(SpriteFrameCache)
- Cocos2d-x -- 纹理缓存(Texture Cache)
- Cocos2d-x 纹理缓存(Texture Cache)
- cocos2d-x——用精灵帧缓存创建动画
- Cocos2d-x 3.0 中文基础教程-精灵帧缓存(SpriteFrameCache)
- cocos2d-x 使用精灵帧缓存池CCSpriteFrameCache
- cocos2d-x 3.0 精灵帧缓存(SpriteFrameCache)
- 【Cocos2d-x 3.0 中文基础教程】精灵帧缓存
- Cocos2d-X研究之v3.x纹理缓存详解
- [Cocos2d-x v3.x官方文档]纹理缓存
- [Cocos2d-x v3.x官方文档]纹理缓存
- 纪念一下我做出来的第一个贪心算法题 还用了结构体喔。
- 数据结构实验之查找七:线性之哈希表
- c++类---隐式的类型转换
- Linux多线程网络编程(一)
- Java和C++区别
- 【Cocos2d-x 3.x】 精灵帧缓存和纹理缓存
- 直接插入排序
- 将java程序做成可执行文件
- iOS-Swift-递归计算Cell高度
- Java finally语句到底是在return之前还是之后执行?
- shell排序
- write 操作文件注意事项
- “南大软院大神养成计划“_第二十一天的学习“
- Android Studio 设置内存大小及原理,优化运行速度