Cocos2d-x学习笔记(十)—— 缓存机制

前端之家收集整理的这篇文章主要介绍了Cocos2d-x学习笔记(十)—— 缓存机制前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

缓存机制

  • Cocos2d-x纹理缓存
  • Cocos2d-x精灵帧缓存
  • Cocos2d-x动画缓存

纹理缓存

事实上,当我们创建精灵时,引擎已经帮我们做了缓存,因而我们下次调用图片可以从缓存获得,减少了内存的消耗,下面我们从源码入手,大致的了解创建精灵时,如何做纹理缓存。
实质上,纹理缓存类似一个字典库,而文件名就是索引的条件,我们可以根据文件名把图片缓存起来,也可以根据文件获取缓存中的图片
Sprite *grossini = Sprite::create("grossini_dance_01.png");<span style="white-space:pre">	</span>// 用图片创建精灵对象
接下来,转向精灵的create()函数的实现:
Sprite* Sprite::create(const std::string& filename)
{
    Sprite *sprite = new (std::nothrow) Sprite();<span style="white-space:pre">	</span>// 用C++的方式,创建一个精灵
    if (sprite && sprite->initWithFile(filename))<span style="white-space:pre">	</span>// 检查精灵对象,并进行文件初始化
    {
        sprite->autorelease();
        return sprite;
    }
    CC_SAFE_DELETE(sprite);<span style="white-space:pre">	</span>// 安全释放精灵对象
    return nullptr;
}
转向精灵文件初始化:
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);<span style="white-space:pre">		</span>// 初始化纹理,将纹理图片进行添加
    }

    // don't release here.
    // when load texture Failed,it's better to get a "transparent" sprite then a crashed program
    // this->release();
    return false;
}

bool Sprite::initWithTexture(Texture2D *texture,const Rect& rect)
{
    return initWithTexture(texture,rect,false);<span style="white-space:pre">	</span>// 初始化纹理
}
转向初始化纹理initWithTexture(texture,rect):
<pre name="code" class="cpp">bool Sprite::initWithTexture(Texture2D *texture,const Rect& rect,bool rotated)
{
    bool result;
    if (Node::init())
    {
        ............
	............

        // 这里是关键点,将纹理图片设置添加到纹理缓存
        setTexture(texture);
	// 设置纹理矩形
        setTextureRect(rect,rotated,rect.size);
        
        _polyInfo.setQuad(&_quad);
        // by default use "Self Render".
        // if the sprite is added to a batchnode,then it will automatically switch to "batchnode Render"
        setBatchNode(nullptr);
        result = true;
    }
    else
    {
        result = false;
    }
    _recursiveDirty = true;
    setDirty(true);
    return result;
}
 
  继而查看将纹理图片设置添加到纹理缓存setTexture(texture);,其他的我们不需要注意,只需看如何将图片添加到纹理缓存: 
 
<pre name="code" class="cpp">void Sprite::setTexture(Texture2D *texture)
{
    // If batchnode,then texture id should be the same
    CCASSERT(! _batchNode || texture->getName() == _batchNode->getTexture()->getName(),"CCSprite: Batched sprites should use the same texture as the batchnode");
    // accept texture==nil as argument
    CCASSERT( !texture || dynamic_cast<Texture2D*>(texture),"setTexture expects a Texture2D. Invalid argument");

    if (texture == nullptr)
    {
        // 根据图片文件名,从纹理缓存中获取纹理图片
        texture = Director::getInstance()->getTextureCache()->getTextureForKey(CC_2x2_WHITE_IMAGE_KEY);

        // 如果获取内容为NULL,说明为缓存至纹理缓存
        if (texture == nullptr)
        {
            Image* image = new (std::nothrow) Image();
            bool isOK = image->initWithRawData(cc_2x2_white_image,sizeof(cc_2x2_white_image),2,8);
            CC_UNUSED_PARAM(isOK);
            CCASSERT(isOK,"The 2x2 empty texture was created unsuccessfully.");

	    // 根据图片文件名,将图片添加到纹理缓存
            texture = Director::getInstance()->getTextureCache()->addImage(image,CC_2x2_WHITE_IMAGE_KEY);
            CC_SAFE_RELEASE(image);
        }
    }

    if (!_batchNode && _texture != texture)
    {
        CC_SAFE_RETAIN(texture);
        CC_SAFE_RELEASE(_texture);
        _texture = texture;
        updateBlendFunc();
    }
}
 
  至此,我们就将图片添加到纹理缓存并创建了一个精灵对象。 
 
接下来,我们看一下如何添加纹理图片,转回
Texture2D *texture = Director::getInstance()->getTextureCache()->addImage(filename);
<pre name="code" class="cpp">Texture2D * TextureCache::addImage(const std::string &path)
{
    Texture2D * texture = nullptr;
    Image* image = nullptr;
    // Split up directory and filename
    // MUTEX:
    // Needed since addImageAsync calls this method from a different thread

    // 通过FileUtils::getInstance()->fullPathForFilename(path);获取完整的路径
    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
                // 缓存纹理及文件名
                VolatileTextureMgr::addImageTexture(texture,fullpath);
#endif
                // _textures为纹理缓存字典,将纹理及路径插入到字典
                _textures.insert( std::make_pair(fullpath,texture) );

                //parse 9-patch info
                this->parseNinePatchImage(image,texture,path);
            }
            else
            {
                CCLOG("cocos2d: Couldn't create texture for file:%s in TextureCache",path.c_str());
            }
        } while (0);
    }

    CC_SAFE_RELEASE(image);

    return texture;
}
 
 
精灵帧缓存
原文链接:https://www.f2er.com/cocos2dx/341817.html

猜你在找的Cocos2d-x相关文章