Cocos2dx学习笔记(8)——三大缓存

小伙伴们可能对缓存不太明白,那么这一章将详细介绍缓存。

本文仅供个人记录和复习,不用于其他用途

什么是缓存

缓存的目的就是:先将所需资源(如纹理图片)加载到内存中,之后再次使用该资源的时候,就可以直接从内存中取出,而不需要重新加载。从而减少了CPU和GPU的内存占用。

纹理缓存

如果游戏需要用到大量纹理图片,比如某个界面需要很多图片,那么可以使用TextureCache。一旦纹理加载完成,下次使用时可使用它返回之前加载的纹理。我们所谓的精灵初始化方法,底层的实现都是将图片加入了纹理缓存。

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

addImage()返回一个Texture2D的引用,如果加入文件失败,则返回之前加入的图片。getTextureForKey()是通过文件名来获取纹理对象,失败则返回nullptr

1
2
3
4
5
6
7
8
9
10
11
12
// 释放当前所有引用计数为1的纹理,即目前没有被使用的纹理。
// 比如新场景创建好后,使用此方法释放没有使用的纹理非常方便。
Director::getInstance()->getTextureCache()->removeUnusedTextures();
// 通过给定的纹理贴图(texture)的关键名(key name)从缓存中删除该纹理贴图
Director::getInstance()->getTextureCache()->removeTextureForKey("Images/grossinis.png");
// 清除加载纹理贴图的记录,如果你收到“内存警告”,请调用该方法。
// 在短期内 : 会释放一些资源文件来防止你的app出现闪退现象
// 在中期内 : 会分配更多资源
// 长远来看 : 没有区别
Director::getInstance()->getTextureCache()->removeAllTextures();

精灵帧缓存

精灵帧一般用于许多小图合成的大图,处理plist文件。所以,精灵帧的配套文件是一个.plist文件和一张大图。精灵帧获取和销毁单例对象和纹理一样,这里不再赘述。

1
2
SpriteFrameCache *frameCache = SpriteFrameCache::getInstance();
frameCache->addSpriteFramesWithFile("boy.plist", "boy.png");

其他的方法在精灵帧一章讲的已经很详细了,这里之讲讲清除缓存的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 从精灵帧缓存中删除一个精灵帧.
SpriteFrameCache::getInstance()->removeSpriteFrameByName(const std::string &name);
// 清除载入精灵帧的字典。如果接收到“Memory Warning”, 请调用这个方法。
// 就眼前来说 : 它将释放一些资源来阻止你的应用崩溃掉。
// 中期的角度 : 它将分配更多的资源。
// 从长远来说 : 它将变成相同的。
SpriteFrameCache::getInstance()->removeSpriteFrames();
// 从一个.plist文件移除多个精灵帧。即:存储在这个文件的精灵帧将被删除。
// 当某个特定的纹理需要被删除时候调用这个方法很方便。
SpriteFrameCache::getInstance()->removeSpriteFramesFromFile(const std::string &plist);
// 移除与特定的纹理结合的所有的精灵帧。
// 当某个特定的纹理需要被删除时候调用这个方法很方便。
SpriteFrameCache::getInstance()->removeSpriteFramesFromTexture(cocos2d::Texture2D *texture);
// 移除没用的精灵帧。保留数为1的精灵帧将被删除。
// 在开始一个新的场景之后调用这个方法很方便。
SpriteFrameCache::getInstance()->removeUnusedSpriteFrames();

纹理、精灵帧、动画帧

精灵帧最开始是用于创建动画,而纹理是最底层也是最有效的图片存储。精灵帧实际上只有一张大图片,也就是一个纹理,它的.plist会存储必要的位置信息,方便截取精灵图片。至于精灵帧和动画帧其实区别不大,不过我们最好认为动画帧是动画的属性,精灵帧只是精灵的属性,而不是将二者混为一谈。

动画缓存

创建动画时,基本的步骤是创建精灵帧,按顺序添加到数组,用Animation读取数组创建动画,这个过程比较繁琐耗时。对于使用频率较高的动画,可以将它加载到动画缓存,要用时直接调用而不是重新加载。

1
2
3
4
void addAnimation(Animation *animation, const std::string& name);
void addAnimationsWithFile(const std::string& plist);
Animation* getAnimation(const std::string& name);
void removeAnimation(const std::string& name);

addAnimation()添加一段动画,并且为之取名,方便之后在缓存中提取这段动画。addAnimationsWithFile()是通过plist文件来添加动画。getAnimation()可以通过相对应的名字,提取动画,该方法返回Animation类指针。removeAnimation()用于移除指定动画。

1
2
3
Animation* animation = Animation::createWithSpriteFrames(arr, 0.04);
AnimationCache::getInstance()->addAnimation(animation, "Explosion");
Animation* animation = AnimationCache::getInstance()->getAnimation("Explosion");

上述代码简要的说明了如何创建动画并加入到缓存,同时从缓存中提取一段动画。

清理缓存顺序

按照由高到低来,先动画缓存,再精灵帧缓存,最后纹理缓存。