cocos2d-x圖片記憶體
阿新 • • 發佈:2019-02-03
一、IOS與圖片記憶體
在IOS上,圖片會被自動縮放到2的N次方大小。比如一張1024*1025的圖片,佔用的記憶體與一張1024*2048的圖片是一致的。圖片佔用記憶體大小的計算的公式是;長*寬*4。這樣一張512*512佔用的記憶體就是512*512*4= 1M。其他尺寸以此類推。(ps:IOS上支援的最大尺寸為2048*2048)。
二、cocos2d-x的圖片快取
cocos2d-x在構造一個精靈的時候會使用spriteWithFile或者spriteWithSpriteFrameName等,無論用哪種方式,cocos2d-x都會將這張圖片載入到快取中,如果是第一次載入這個圖片,那就會先將這張圖片載入到快取,然後從快取讀取。如果快取中已經存在,則直接從快取中提取,免除了載入過程。
圖片的快取主要由以下兩個類來處理:CCSpriteFrameCache,CCTextureCache
CCSpriteFrameCache載入的是一張拼接過的大圖,每一個小圖只是大圖中的一個區域,這些區域資訊都在plist檔案中儲存。用的時候只需要根據小圖的名稱就可以載入到這個區域。
CCTextureCache是普通的圖片快取,我們所有直接載入的圖片都會預設放到這個快取這那更,以提高呼叫效率。
因此,每次載入一張圖片,或者通過plist載入一張拼接圖時,都會將整張圖片載入到記憶體中。如果不去釋放,那就會一直佔用著。
三、渲染記憶體
不要以為,計算記憶體時,只計算載入到快取中的記憶體就可以了,以一張1024*1024的圖片為例。
CCSprite *pSprite = CCSprite::spriteWithFile("a.png");
呼叫上邊這行程式碼以後,可以在LEAKS工具中看到,增加了大約4M的記憶體,然後接著呼叫addChild(pSprite);
這時,記憶體又增加了4M,也就是,一張圖片,如果需要渲染的話,那它所佔用的記憶體將要*2。
再看看通過plist載入的圖片,比如這張大圖片為2048*2048。想要載入其中的一張32*32的小圖片
CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFrameWithFile("b.plist");
此時記憶體增加16M
CCSprite *pSpriteFrame =CCSpritewithSpriteFrameName("b1,png");
b.png大小為32*32,想著也就是增加一點點記憶體,可實際情況是增加16M記憶體,也就是隻要渲染了其中的一部分,那麼整張圖片都要一起被載入。
但是情況不是那麼糟糕,這些已經渲染的圖片,如果再次載入的話,記憶體是不會在繼續升高的,比如又增加了100個b.plist的另一個區域,圖片記憶體還是增加16+16=32M,而不會繼續上升。
四、快取釋放
如果遊戲有很多場景,在切換場景的時候可以把前一個場景的記憶體全部釋放,防止總記憶體過高。
CCTextureCache::sharedTextureCache()->removeAllTextures(); //釋放到目前為止所有載入的圖片
CCTextureCache::sharedTextureCache()->removeUnusedTextures();//將引用計數器為1的圖片釋放掉CCTextureCache::sharedTextureCache()->removeTexture();//單獨釋放某個圖片
CCSpriteFrameCache與CCTextureCache釋放的方法差不多。
值得注意的是釋放的時機,一般在切換場景的時候釋放資源,如果從A場景切換到B場景,呼叫的函式順序為B::init()---->a::exit()-------->B::onEnter()可如果使用了切換效果,比如CTransitionJumpZoom::transitionWithDuration這樣的函式,則函式的呼叫順序變為B::init()---->B::onEnter()------->A::exit()而且第二種方式會有一瞬間將兩個場景的資源疊加在一起,若果不採取過度,很可能會因為記憶體吃緊而崩潰。
有時候強制釋放全部資源時,會使某個正在執行的動畫失去引用而彈出異常,可以呼叫CCActionManager::sharedManager()->removeAllActions()來解決。
五、記憶體的優化
優化的心得就是儘量去拼接圖片,使圖片變長儘可能的保持2的N次方並且裝的很滿。但要注意,有邏輯關係的圖片儘量打包在一張大圖裡,另外一點就是打包的時候要考慮到層的分佈。因為為了渲染效率可能會用到CCSpriteBatchNode;同一個BatchNode裡的圖片都是位於一個層級的,因此必須根據各個圖片的層級關係,打包到不同的plist裡。有時記憶體和效率不可以兼得,只能儘量平衡了。