cocos2d缓存机制

cocos2d的缓存机制主要设置到CCTextureCache、CCSpriteFrameCache、CCAnimationCache。下面来简单介绍一下这三种缓存机制。

CCTextureCache

游戏还没运行时我们的图片资源都是保存在外部存储器(硬盘、闪存)中,当我们运行游戏,把图片显示出来时,这个流程就是从外部存储器读取图片数据到内存,然后根据内存数据进行渲染,这整个步骤比较耗时的操作是从外部存储器读取数据到内存的过程。你想在一瞬间显示大量的图片,如果采用的是每张图片顺序执行(内部存储-内存-渲染),那么会发现这些图片展现出来会有明显的时间差,会给人卡顿的感觉。所以一般的游戏在打开游戏的时候都会有加载资源的界面,在这个界面把大量需要在下一个界面显示的资源从内部存储器读取到内存(这个就是所谓的缓存),最后在需要显示的的时候才根据内存数据进行渲染。

Texture2D * TextureCache::addImage(const std::string &path)
{
    Texture2D * texture = nullptr;
    Image* image = nullptr;

    std::string fullpath = FileUtils::getInstance()->fullPathForFilename(path);
    if (fullpath.size() == 0)
    {
        return nullptr;
    }
    auto it = _textures.find(fullpath);
    if( it != _textures.end() )
        texture = it->second;

    if (! texture)
    {
        // all images are handled by UIImage except PVR extension that is handled by our own handler
        do 
        {
            image = new (std::nothrow) Image();
            CC_BREAK_IF(nullptr == image);

            bool bRet = image->initWithImageFile(fullpath);
            CC_BREAK_IF(!bRet);

            texture = new (std::nothrow) Texture2D();

            if( texture && texture->initWithImage(image) )
            {
#if CC_ENABLE_CACHE_TEXTURE_DATA
                // cache the texture file name
                VolatileTextureMgr::addImageTexture(texture, fullpath);
#endif
                // texture already retained, no need to re-retain it
                _textures.insert( std::make_pair(fullpath, texture) );
            }

        } while (0);
    }

    CC_SAFE_RELEASE(image);

    return texture;
}

从上面代码可以看到,addImage(const std::string &path)方法根据传入的图片地址,返回一个已存在的texture或新生成一个texture并返回。

通过下面Sprite的create方法可以看到里面也调用了addImage方法:

bool Sprite::initWithFile(const std::string& filename)
{
    CCASSERT(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);
    }

    return false;
}

CCSpriteFrameCache

这个类是用来缓存有多张碎图合成的大图,主要通过addSpriteFramesWithFile方法将图片载入内存生成Texture对象

void SpriteFrameCache::addSpriteFramesWithFile(const std::string& plist)
{
    CCASSERT(plist.size()>0, "plist filename should not be nullptr");

    if (_loadedFileNames->find(plist) == _loadedFileNames->end())
    {
        std::string fullPath = FileUtils::getInstance()->fullPathForFilename(plist);
        ValueMap dict = FileUtils::getInstance()->getValueMapFromFile(fullPath);

        string texturePath("");

        if (dict.find("metadata") != dict.end())
        {
            ValueMap& metadataDict = dict["metadata"].asValueMap();
            // try to read  texture file name from meta data
            texturePath = metadataDict["textureFileName"].asString();
        }

        if (!texturePath.empty())
        {
            // build texture path relative to plist file
            texturePath = FileUtils::getInstance()->fullPathFromRelativeFile(texturePath.c_str(), plist);
        }
        else
        {
            // build texture path by replacing file extension
            texturePath = plist;

            // remove .xxx
            size_t startPos = texturePath.find_last_of("."); 
            texturePath = texturePath.erase(startPos);

            // append .png
            texturePath = texturePath.append(".png");
        }
        //根据得到的图片路径生成texture对象
        Texture2D *texture = Director::getInstance()->getTextureCache()->addImage(texturePath.c_str());

        if (texture)
        {
            addSpriteFramesWithDictionary(dict, texture);
            _loadedFileNames->insert(plist);
        }

    }
}

然后根据plist文件和texture对象,生成相对于的spriteFrame对象。主要代码如下:

void SpriteFrameCache::addSpriteFramesWithDictionary(ValueMap& dictionary, Texture2D* texture)
{
 
    for (auto iter = framesDict.begin(); iter != framesDict.end(); ++iter)
    {
        ValueMap& frameDict = iter->second.asValueMap();
        std::string spriteFrameName = iter->first;
        SpriteFrame* spriteFrame = _spriteFrames.at(spriteFrameName);
        if (spriteFrame)
        {
            continue;
        }
        
        if(format == 0) 
        {
   
            // create frame
            spriteFrame = SpriteFrame::createWithTexture(texture,
                                                         Rect(x, y, w, h),
                                                         false,
                                                         Vec2(ox, oy),
                                                         Size((float)ow, (float)oh)
                                                         );
        } 
        else if(format == 1 || format == 2) 
        {
          
            // create frame
            spriteFrame = SpriteFrame::createWithTexture(texture,
                                                         frame,
                                                         rotated,
                                                         offset,
                                                         sourceSize
                                                         );
        } 
        else if (format == 3)
        {
            
            // create frame
            spriteFrame = SpriteFrame::createWithTexture(texture,
                                                         Rect(textureRect.origin.x, textureRect.origin.y, spriteSize.width, spriteSize.height),
                                                         textureRotated,
                                                         spriteOffset,
                                                         spriteSourceSize);
        }

        // add sprite frame
        _spriteFrames.insert(spriteFrameName, spriteFrame);
    }
}

最后创建sprite时可以用Sprite* Sprite::createWithSpriteFrameName(const std::string& spriteFrameName)创建sprite

CCAnimationCache

这个用法也是比较简单,主要是将动画缓存起来,需要用的时候再调用

void AnimationCache::addAnimation(Animation *animation, const std::string& name)
{
    _animations.insert(name, animation);
}
Animation* AnimationCache::getAnimation(const std::string& name)
{
    return _animations.at(name);
}

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值