Cocos 2 d-lua自動再ロードSpriteFrames


昨日iOSで清宮Q伝をテストして、何本か游んで突然間違いを報告しました.
[LUA-print] ASSERT FAILED ON LUA EXECUTE: Invalid spriteFrameName :spsheet_1/img_004

当时は何も知らなかった、合図spsheet_1ゲームに入ったときにロードされたに違いないし、合図内の他の画像が正常に表示されているのに、どうして急に見つからないのだろうか.
急いで日記をめくって、間違いを報告する前にやはり元凶を見つけた.
2016-05-03 16:09:34.053 game[24503:15980923] Received memory warning.

メモリの警告を受けたときに何をしたかを見てみましょう.AppController.mmを開きます.
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
     cocos2d::Director::getInstance()->purgeCachedData();
}

さらにCCDirector.cppに入ります.
void Director::purgeCachedData(void)
{
    FontFNT::purgeCachedData();
    FontAtlasCache::purgeCachedData();

    if (s_SharedDirector->getOpenGLView())
    {
        //  
        SpriteFrameCache::getInstance()->removeUnusedSpriteFrames();
        _textureCache->removeUnusedTextures();

        // Note: some tests such as ActionsTest are leaking refcounted textures
        // There should be no test textures left in the cache
        log("%s
"
, _textureCache->getCachedTextureInfo().c_str()); } FileUtils::getInstance()->purgeCachedEntries(); }

はい、メモリ警告時にcococos 2 d-xは、フォント、テクスチャ、spriteFrameなど、キャッシュデータをクリーンアップします.では問題ですが、ゲームの途中で、突然キャッシュがクリアされましたが、どうすればいいのでしょうか.cococos 2 d−xは自動回復機構を持たないことは明らかである.
自分で書いて適当に使うしかない.(>﹏<)
原理はこうです.
  • cc.SpriteFrameCache:getInstance():addSpriteFrames(plist)を呼び出すと、plistのframenameとplistの関係を記録します.擬似コードは以下の通りです.
  • local _map = {}
    function cacheSpritePlist(plist)
        -- avoid muliple loading of the same plist
        if tableValuesContain(_map, plist) then
            logi("Frames Already added:", plist)
            return
        end
        -- read plist data
        local data = __readPList(plist)
        -- record framename -> plistname
        for fname, _ in pairs(data.frames) do
            self.map[fname] = plist
        end
    end
  • sprite frameを設定する場所、たとえば
  • --  sprite spriteframe
    sprite:setSpriteFrame(framename)
    --  spriteframe sprite
    cc.Sprite:createWithSpriteFrameName(framename)
    --  

    spriteFrameが存在するかどうかを事前にチェックする必要があります.存在しない場合は、対応するplistを検索し、再ロードします.擬似コードは次のとおりです.
    function reload(framename)
        local plist = _map[framename]
        cc.SpriteFrameCache:getInstance():addSpriteFrames(plist)
    end
    
    local SpCache = cc.SpriteFrameCache:getInstance() 
    function checkFrame(framename)
        if not SpCache:getSpriteFrame(framename) then
            reload(framename)
        end
    end

    はい、多分そうです.cleanup関数を追加して、ある合図が使用されなくなったら、_mapの中のこの合図に関するデータを全部整理して、メモリ空間を節約して、この偽コードは書きません.
    テストしてみたので,これ以上間違いを報告することはない.
    このような問題は以前にも遭遇したことがあるはずで、もっと良い解決策があるかどうか分かりません.私はいつもこれがCocos 2 d-xが背負うべき鍋だと感じます.╮(╯_╰)╭