[Cocos2d-x v3.x官方文档]纹理缓存

来源:互联网 发布:台北故宫知乎 编辑:程序博客网 时间:2024/05/17 07:18

概述

在游戏中需要加载大量的纹理图片,这些操作都是很耗内存和资源的。

 

当游戏中有个界面用到的图片非常多,第一次点进这界面时速度非常慢(因为要加载绘制很多图片)出现卡顿,我们可以使用TextureCache提前异步加载纹理,等加载结束,进入到这个界面再使用这些图片速度就会非常快。

 

Texture2D: 纹理,即图片加载入内存后供CPU和GPU操作的贴图对象。  

TextureCache(纹理缓存),用于加载和管理纹理。一旦纹理加载完成,下次使用时可使用它返回之前加载的纹理,从而减少对GPU和CPU内存的占用。

 

常用的方法

当你创建一个精灵,你一般会使用Sprite::create(pszFileName)。假如你去看Sprite::create(pszFileName)的实现方式,你将看到它将这个图片增加到纹理缓存中去了:

  1. Sprite* Sprite::create(const std::string& filename) 
  2.     Sprite *sprite = new Sprite(); 
  3.     if (sprite && sprite->initWithFile(filename)) 
  4.     { 
  5.         sprite->autorelease(); 
  6.         return sprite; 
  7.     }  
  8.     _SAFE_DELETE(sprite);  
  9.     return nullptr; 
  10.  
  11. bool Sprite::initWithFile(const std::string& filename)  
  12.  
  13.     ASSERT(filename.size()>0, "Invalid filename for sprite"); 
  14.  
  15.     Texture2D *texture = Director::getInstance()->getTextureCache()->addImage(filename); 
  16.  
  17.     if (texture) 
  18.  
  19.     { 
  20.  
  21.         Rect rect = Rect::ZERO; 
  22.  
  23.         rect.size = texture->getContentSize(); 
  24.  
  25.         return initWithTexture(texture, rect); 
  26.  
  27.     } 
  28.  
  29.     // don't release here. 
  30.  
  31.     // when load texture failed, it's better to get a "transparent" sprite then a crashed program 
  32.  
  33.     // this->release(); 
  34.  
  35.     return false
  36.  

 

上面代码显示在控制加载纹理。一旦这个纹理被加载了,在下一时刻就会返回之前加载的纹理引用,并且减少加载的时候瞬间增加的内存。(详细API请看TextureCache API)

 

获取TextureCache

在3.0版本中,TextureCache不再作为单例模式使用。作为Director的成员变量,通过以下方式获取:

  1. Director::getInstance()->getTextureCache(); 

 

获取纹理

如果文件名以前没有被加载时,它会创建一个新的Texture2D 对象,它会返回它。它将使用文件名作为key否则,它会返回一个引用先前加载的图像。

TextureCache屏蔽了加载纹理的许多细节;

addImage函数会返回一个纹理Texture2D的引用,可能是新加载到内存的,也可能是之前已经存在的;

  1. Texture2D *texture = Director::getInstance()->getTextureCache()->addImage(filename); 

 

也可以通过getTextureForKey方法来获得这个key所对应的纹理缓存,如果这个Key对应的纹理不存在,那么就返回NULL。

  1. Texture2D *texture = Director::getInstance()->getTextureCache()->getTextureForKey(textureKeyName); 

 

异步加载纹理

TextureCache类还支持异步加载资源的功能,利用addImageAsync方法。你可以很方面地给addImageAsync方法添加一个回调方法,这样,当纹理异步加载结束的时候,可以得到通知。

 

你可以选择异步加载方式,这样你就可以为loading场景增加一个进度条。关键代码如下:

  1. TextureCacheTest::TextureCacheTest() 
  2.  
  3. : _numberOfSprites(20) 
  4.  
  5. , _numberOfLoadedSprites(0) 
  6.  
  7.  
  8.     auto size = Director::getInstance()->getWinSize(); 
  9.  
  10.     _labelLoading = Label::createWithTTF("loading...""fonts/arial.ttf", 15); 
  11.  
  12.     _labelPercent = Label::createWithTTF("%0""fonts/arial.ttf", 15); 
  13.  
  14.     _labelLoading->setPosition(Point(size.width / 2, size.height / 2 - 20)); 
  15.  
  16.     _labelPercent->setPosition(Point(size.width / 2, size.height / 2 + 20)); 
  17.  
  18.     this->addChild(_labelLoading); 
  19.  
  20.     this->addChild(_labelPercent); 
  21.  
  22.     // load textrues 
  23.  
  24.     Director::getInstance()->getTextureCache()->addImageAsync("Images/HelloWorld.png", _CALLBACK_1(TextureCacheTest::loadingCallBack, this)); 
  25.  
  26.     Director::getInstance()->getTextureCache()->addImageAsync("Images/grossini.png", _CALLBACK_1(TextureCacheTest::loadingCallBack, this)); 
  27.  
  28.     Director::getInstance()->getTextureCache()->addImageAsync("Images/grossini_dance_01.png", _CALLBACK_1(TextureCacheTest::loadingCallBack, this)); 
  29.  
  30.     .... 
  31.  
  32.  
  33. void TextureCacheTest::loadingCallBack(cocos2d::Texture2D *texture) 
  34.  
  35.  
  36.     ++_numberOfLoadedSprites; 
  37.  
  38.     char tmp[10]; 
  39.  
  40.     sprintf(tmp,"%%%d", (int)(((float)_numberOfLoadedSprites / _numberOfSprites) * 100)); 
  41.  
  42.     _labelPercent->setString(tmp); 
  43.  
  44.     if (_numberOfLoadedSprites == _numberOfSprites) 
  45.  
  46.     { 
  47.  
  48.         this->removeChild(_labelLoading, true); 
  49.  
  50.         this->removeChild(_labelPercent, true); 
  51.  
  52.         addSprite(); 
  53.  
  54.     } 
  55.  

 

 清理缓存

removeUnusedTextures则会释放当前所有引用计数为1的纹理,即目前没有被使用的纹理。比如新场景创建好后,使用此方法释放没有使用的纹理非常方便。

  1. Director::getInstance()->getTextureCache()->removeUnusedTextures(); 

 

当没有其它对象(比如sprite)持有纹理的引用的时候,纹理仍然会存在内存之间。基于这一点,我们可以立马从缓存中移除出去,这样,当纹理不存需要的时候,马上就会从内存中释放掉。如下代码所示:

  1. Director::getInstance()->getTextureCache()->removeTextureForKey("Images/grossinis_sister2.png"); 

 

当收到"Memory Warning"时,可以调用removeAllTextures()方法。在短期内: 它还将释放一些资源,防止您的应用程序被杀害; 中期: 它将分配更多的资源;从长远来看:它会是相同的。

  1. Director::getInstance()->getTextureCache()->removeAllTextures(); 

 

0 0