如何優化cocos2d/x程序的內存使用和程序大小

在我完成第一個遊戲項目的時候,我深切地意識到“使用cocos2d來製作遊戲的開發者們,他們大多會被cocos2d的內存問題所困擾”。而我剛開始接觸cocos2d的時候,社區裏面的人們討論了一個非常有意義的話題:“請簡單地講述你認爲新手cocos2d程序員在他開始編碼之前,最應該先知道,或者應該關注和注意的事項。”這個問題的答案很多,有人講是“如何加載和保存遊戲數據”,有人講的是“如何實現有限狀態機”等等。而最吸引我的則是,有一個人講到,新手cocos2d程序員或者新手cocoa程序,他們所遇到的80%的問題都與內存相關。

 

因爲有着c/c++背景的我,看到這句話的時候,很是贊同,因此剛開始cocos2d編程的時候格外注意內存方面的問題。即便如此,在我完成自己第一個遊戲的過程中,還是遇到了大量的內存問題,它們讓我頭疼,讓我睡不着覺。慶幸的是,我通過社區都找到了答案並且解決了我的問題。

 

我在《我的第一個遊戲FoodieTheBug完成之後的幾點心得體會》這篇博文中也講述過一些內存方面的使用心得。但是,不夠具體,我當時想講的內容有很多。因爲有些難以用文字具象化,我也就偷了一回懶了。這次,當我看到Steffen Itterheim寫了兩篇這麼經典的優化cocos2d內存使用和程序大小的文章之後,我有一種“於我心有慼慼焉”的感覺。我迫不及待地想跟大家分享,可惜很多人抱怨說訪問不了,被牆了等等。可能也有一些同行,對E文不是很感冒。趁着週末,我花一個下午的時間,給大家翻譯一下,與大家共勉。

 

全文如下:

我目前正完成我的最後一個合約項目。在這個項目的最後階段,我需要考慮的一件事情就是如何優化遊戲的內存使用。

 

在今天的iDevBlogADay文章中,我將向大家講述,我是如何減少25-30MB遊戲內存消耗的(現在遊戲消耗內存90-95MB,我還通過這個過程,消除了一些由於內存警告而引起的程序崩潰問題)。同時,我還將遊戲程序的大小從25MB減少到了20MB以下(如果蘋果沒有在不久前將蜂窩網下載應用的限制從20MB提高到50MB的話,那麼我這個小的優化就太棒了,它可以潛在地給我帶來更多的下載量)。

我還會給大家介紹,如何在你加載遊戲資源的時候展示一個帶有動畫的Loading界面,我還會加入一些最佳實踐和小技巧。

 

什麼消耗了90%的內存?

大家猜一下:)

在大部分情況下,是紋理(textures)消耗了遊戲程序大量的內存。因此,紋理是我們首要考慮優化的對象,特別是當你碰到內存警告的問題的時候。

 

避免一個接一個地加載PNG和JPG紋理(他們之間至少等待一幀)

cocos2d裏面紋理加載分爲兩個階段:1.從圖片文件中創建一個UIImage對象。2.以這個創建好的UIImage對象來創建CCTexture2D對象。這意味着,當一個紋理被加載的時候,在短時候內,它會消耗兩倍於它本身內存佔用的內存大小。(譯註:爲什麼只是短時間內呢?因爲autoRelease pool和引用計數的關係,臨時創建的UIImage對象會被回收。)

當你在一個方法體內,接二連三地加載4個紋理的時候,這個內存問題會變得更加糟糕。因爲在這個方法還沒結束之前,每一個紋理都會消耗兩倍於它本身的內存。

我不是很確定,現在的cocos2d是否仍然如此。或者這種情況是否只適用於手工引用計數管理,或許ARC不會如此呢?我習慣於按順序加載紋理,但是在加載下一個紋理之前要等待一幀。這將會使得任何紋理加載的消耗對內存的壓力降低。因爲等待一幀,引用計數會把臨時的UIImage對象釋放掉,減少內存壓力。此外,在後續的文章中,如果你想在背景線程中按序加載紋理的話,也可以採用這種方法。

 

不要使用JPG圖片!

cocos2d-iphone使用JPG紋理的時候有一個問題。因爲JPG紋理在加載的時候,會實時地轉化爲PNG格式的紋理。這意味着cocos2d-iphone加載紋理是非常慢的(這裏有演示),而且JPG紋理將消耗三倍於本身內存佔用大小的內存。

一個2048*2048大小的紋理會消耗16M的內存。當你加載它的時候,在短時間內,它將消耗32MB內存。現在,如果這個圖片是JPG格式,你會看到這個數字會達到48MB,因爲額外的UIImage對象的創建。雖然,最終內存都會降到16M,但是,那一個時刻的內存飆高,足以讓os殺死你的遊戲進程,造成crash,影響用戶體驗。

JPG不論在加載速度和內存消耗方面都很差。所以,千萬不要使用JPG!

 

忽視文件圖片大小

這種情況,我見到很多。它乍聽起來可能覺得有點荒誕,但事實如此,因爲它需要關於文件格式的知識,而這些知識並不是每一個程序員都瞭解的。我經常聽到的論斷就是“嘿!我的程序不可能有內存警告,我所有的圖片資源加起來還不到30MB!”。

怎麼說呢,因爲圖片文件大小和紋理內存佔用是兩碼事。假設他們是帳篷。圖片文件就相當於帳篷被裝在行李箱。但是,如果你想要使用帳篷的話,它必須被撐起來,被“膨脹”。

圖片文件和紋理的關係與此類似。圖片文件大多是壓縮過的,它們被使用的話必須先解壓縮,然後才能會GPU所處理,變成我們熟知的紋理。一個2048*2048的png圖片,採用32位顏色深度編碼,那麼它在磁盤上佔用空間只有2MB。但是,如果變成紋理,它將消耗16MB的內存!

當然,減少紋理佔用內存大小是有辦法滴。

 

使用16-bit紋理

最快速地減少紋理內存佔用的辦法就是把它們作爲16位顏色深度的紋理來加載。cocos2d默認的紋理像素格式是32位顏色深度。如果把顏色深度減半,那麼內存消耗也就可以減少一半。並且這還會帶來渲染效率的提升,大約提高10%。

你可以使用CCTexture2D對象的類方法setDefaultAlphaPixelFormat來更改默認的紋理像素格式,代碼如下:

[CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGB5A1];
[[CCTextureCache sharedTextureCache] addImage:@"ui.png"];

 

這裏有個問題:首先,紋理像素格式的改變會影響後面加載的所有紋理。因此,如果你想後面加載紋理使用不同的像素格式的話,必須再調用此方法,並且重新設置一遍像素格式。

其次,如果你的CCTexture2D設置的像素格式與圖片本身的像素格式不匹配的話,就會導致顯示嚴重失真。比如顏色不對,或者透明度不對等等。

 

有哪些比較有用的紋理像素格式呢?

generate 32-bit textures: kCCTexture2DPixelFormat_RGBA8888 (default)
generate 16-bit textures: kCCTexture2DPixelFormat_RGBA4444
generate 16-bit textures: kCCTexture2DPixelFormat_RGB5A1
generate 16-bit textures: kCCTexture2DPixelFormat_RGB565 (no alpha)

 

RGBA8888是默認的格式。對於16位的紋理來說,使用RGB565可以獲得最佳顏色質量,因爲16位全部用來顯示顏色:總共有65536總顏色值。但是,這裏有個缺點,除非圖片是矩形的,並且沒有透明像素。所以RBG565格式比較適合背景圖片和一些矩形的用戶控件。

RBG5A1格式使用一位顏色來表示alpha通道,因此圖片可以擁有透明區域。只是,1位似乎有點不夠用,它只能表示32768種可用顏色值。而且圖片要麼只能全部是透明像素,或者全部是不透明的像素。因爲一位的alpha通道的緣故,所以沒有中間值。但是你可以使用fade in/out動作來改變紋理的opacity屬性。

如果你的圖片包含有半透明的區域,那麼RBGA4444格式很有用。它允許每一個像素值有127個alpha值,因此透明效率與RGBA8888格式的紋理差別不是很大。但是,由於顏色總量減少至4096,所以,RBGA4444是16位圖片格式裏面顏色質量最差的。

現在,你可以得到16位紋理的不足之處了:它由於顏色總量的減少,有一些圖片顯示起來可能會失真,而且可能會產生“梯度”。

 

使16位紋理看起來更棒

幸運的是,我們有TexturePacker.(後面簡稱TP)

TP有一個特性叫做“抖動”,它可以使得原本由於顏色數量減少而產生的失真問題得到改善。(TP裏面有很多抖動算法,關於這些算法,讀者可以參考我翻譯的另一篇文章)。

特別是在擁有Retina顯示的像素密度下,你幾乎看不出16位與32位的紋理之間的顯示差別。當然,前提是你需要採用“抖動”算法。

cocos2d默認的顏色深度將會把所有的紋理都渲染到16位的color framebuffer裏面,然後再顯示到你的設備屏幕上面。既然這樣,我們爲什麼不把所有的紋理的格式都弄成16位呢,32位又有什麼用呢?反正它本來就會渲染到16位的framebuffer上去的。這個問題有點太底層了,我不想深挖下去,而且我也不適合解釋這個問題。(譯者:哈哈,知之爲知之,不知爲不知)

 

使用NPOT紋理

NOPT是“non power of two”的縮寫,譯作“不是2的冪”。NPOT stands for “non power of two”. 在cocos2d1.x的時候,你必須在ccConfig.h文件中開啓對NPOT的支持,但是,cocos2d 2.x就不需要了,它默認是支持NPOT的。所有3代(iphone 3GS)以後的ios設置都支持cocos2d 2.x(因爲它們支持OpenGL ES2.0),所以也都能支持NPOT紋理。

如果紋理圖集(texture atlas)使用NPOT的紋理,它將有一個具大的優勢:它允許TP更好地壓縮紋理。因此,我們會更少地浪費紋理圖集的空白區域。而且,這樣的紋理在加載的時候,會少使用1%到49%左右的內存。而且你可以使用TP強制生成NPOT的紋理。(你只需要勾選“allow free size”即可)

爲什麼要關心NPOT呢?因爲蘋果的OpenGL驅動有一個bug,導致如果使用POT的紋理,則會產生額外33%的內存消耗

 

默認使用PVR格式的紋理

TP讓你可以創建PVR格式的紋理。除了PVR紋理支持NPOT外,它們不僅可以不是2的冪,而且還可以不是方形的。

PVR是最靈活的紋理文件格式。除了支持標準的未壓縮的RGB圖片格式外,不支持有損壓縮的pvrtc格式。另外,未壓縮的pvr格式的紋理的內存消耗非常地低。不像png圖片那樣要消耗2倍於本身內存佔用大小的內存,pvr格式只需要消耗紋理本身內存大小再加上一點點處理該圖片格式的內存大小。

pvr格式的一個缺點就是,你不能在Mac上面打開查看。但是,如果你安裝了TP的話,就可以使用TP自帶的pvr圖片瀏覽器來瀏覽pvr格式的圖片了。(強烈建議大家購買TP,支持TP,不要再盜版了)

使用PVR格式的文件幾乎沒有缺點。此外,它還可以極大地提高加載速度,後面我會解釋到。

 

使用pvr.ccz文件格式

在三種可選用的pvr文件格式中,優先選擇pvr.ccz格式。它是專門爲cocos2d和TP設計的。在TP裏面,這是它生成的最小的pvr文件。而且pvr.ccz格式比其它任何文件格式的加載速度都要快

當在cocos2d裏面使用pvr格式的紋理時,只使用pvr.ccz格式,不要使用其它格式!因爲它加載速度超快,而且加載的時候使用更少的內存!

 

當視覺察覺不出來的時候,可以考慮使用PVRTC壓縮

PVR紋理支持PVRTC紋理壓縮格式。它主要是採用的有損壓縮。如果拿PVRTC圖片與JPG圖片作對比的話,它只有JPG圖片中等質量,但是,最大的好處是可以不用在內存裏面解壓縮紋理。

這裏把32位的png圖片(左邊)與最佳質量的PVRTC4(4位)圖片(點擊圖片查看完整的大小)作對比:

注意,在一些高對比度的地方,明顯有一些瑕疵。有顏色梯度的地方看起來還好一點。

PVRTC肯定不是大部分遊戲想要採用的紋理格式。但是,它們對於粒子效果來說,非常適用。因爲那些小的粒子在不停地移動、旋轉、縮放,所以你很難看出一些視覺瑕疵。

 

PVRTC壓縮圖片格式

TP提供的PVR格式不僅有上面兩種,還包括TC2和TC4這兩種沒有alpha通道的格式。

這裏的alpha和16位紋理的alpha是一樣的。沒有alpha通道意味着圖片裏面沒有透明像素,但是,更多的顏色位會用來表示顏色,那麼顏色質量看起來也會更好一些。

有時候,PVRTC圖片格式指的是使用4位或者2位顏色值 ,但是,並不完全是那樣。PVRTC圖片格式可以編碼更多的顏色值。

 

預先加載所有的紋理

就像標題所說,盡你所能,一定要預先加載所有的紋理。如果你的所有的紋理加起來不超過80MB內存消耗的話(指的是擁有Retina顯示的設備,非Retina的減半考慮),你可以在第一個loading場景的時候就全部加載進來。

這樣做最大的好處在於,你的遊戲體驗會表現得非常平滑,而且你不需要再擔心資源的加載和卸載問題了。

這樣也使得你可以讓每一個紋理都使用合適的紋理像素格式,而且可以更方便地找出其它與紋理無關的內存問題。因爲如果與紋理有關,那麼在第一次加載所有的紋理的時候,這個問題就會暴露出來的。如果所有的紋理都加載完畢,這時候再出現內存問題,那麼肯定就與紋理無關了,而是其它的問題了。

如果你知道問題與紋理無關的話,那麼你查找剩下的內存問題將會變得更加簡單。而且你避免了前面說的這種情況:當2048*2048的紋理加載的時候,它本來只需要消耗16MB內存,但是短時間會衝到32MB內存。後面會提出一種方法來解決“間歇性內存飆高”(“譯者發明滴”)的方法。(譯者:希望下次開發者的對話中“間歇性內存飆高”的說法會出現,呵呵)

 

按照紋理size從大到小的順序加載紋理

由於加載紋理時額外的內存消耗問題,所以,採用按紋理size從大到小的方式來加載紋理是一個最佳實踐。

假設,你有一個佔內存16MB的紋理和四個佔用內存4MB的紋理。如果你首先加載4MB的紋理,這個程序將會使用16MB的內存,而當它加載第四張紋理的時候,短時間內會飆到20MB。這時,你要加載16MB的那個紋理了,內存會馬上飆到48MB(4*4 + 16*2),然後再降到32MB(4*4 + 16)。

但是,反過來,你先加載16MB的紋理,然後短時候內飆到32MB。然後又降到16MB。這時候,你再依次加載剩下的4個4MB的,這時,最多會彪到(4*3 + 4*2 + 16=36)MB。

在這兩種情況下,內存的峯值使用相差12MB,要知道,可能就是這12MB會斷送你的遊戲進程的小命哦!

 

避免在收到內存警告消息的時候清除緩存

我有時候看到了一種奇怪的“自己開槍打自己的腳”的行爲:紋理已經全部在Loading場景裏面加載完畢了,這時候,內存警告發生了,然後cocos2d就會把沒有使用的紋理從緩存中釋放掉。

聽起來不錯,沒有使用到的紋理都被釋放掉了,但是!。。。

你剛剛把所有的紋理都加載進來,還沒有進入任何一個場景中(此時所有的紋理都被當作“unused”),但是馬上被全部從texture cache中移除出去。可是,你又需要在其它場景中使用它們。怎麼辦?你需要接着判斷,如果有紋理沒有加載,就繼續加載。但是,一加載,由於“間歇性內存飆高”,又馬上收到了內存警告,再釋放,再判斷,再加載。。。。 我的天,這是一個死循環啊!這也能解釋爲什麼有些童鞋,在loading場景完了之後進入下一個場景 的時候很卡的原因了。

現在,當我收到內存警告的時候,我的做法是----什麼也不做。內存警告仍然在發生,但是,它只是在程序剛開始加載的時候。我知道這是爲什麼,因爲“間歇性內存飆高”嘛,所以,我不去管它。(但是,如果是遊戲過程中再收到內存警告,你就要注意了,因爲這時候可能你有內存泄漏了!!!)

我有時候會想辦法改善一下,通過移除掉一些不使用的紋理和一些只有在很特殊的場景纔會使用的圖片(比如settings界面,玩家是不經常訪問的)。然後,不管什麼時候,當我需要某張圖片的時候,我會首先檢查一下該sprite frame是否在cache中,如果沒有就加載。你會在後面看到具體的做法。

 

理解在什麼時候、在哪裏去清除緩存

不要隨機清除緩存,也可以心想着釋放一些內存而去移除沒有使用的紋理。那不是好的代碼設計。有時候,它甚至會增加加載次數,並多次引發“間歇內存飆高”。分析你的程序的內存使用,看看內存裏面到底有什麼,以及什麼應該被清除,然後只清除該清除的。

你可以使用dumpCachedTextureInfo方法來觀察哪些紋理被緩存了:

[[CCTextureCache sharedTextureCache] dumpCachedTextureInfo];

 

這個方法的輸出如下:(爲了清楚起見,我把那些與-hd後綴有關的信息屏蔽掉了) 

複製代碼
cocos2d: "ingamescorefont.png" rc=9 name=ingamescorefont-hd.png id=13 128 x 64 @ 32 bpp => 32 KB
cocos2d: "ui.png" rc=15 name=ui-hd.png id=5 2048 x 2048 @ 16 bpp => 8192 KB
cocos2d: "ui-ingame.png" rc=36 name=ui-ingame-hd.png id=8 1024 x 1024 @ 16 bpp => 2048 KB
cocos2d: "digits.png" rc=13 name=digits-hd.png id=10 512 x 64 @ 16 bpp => 64 KB
cocos2d: "hilfe.png" rc=27 name=hilfe-hd.png id=6 1024 x 2048 @ 32 bpp => 8192 KB
cocos2d: "settings.png" rc=8 name=settings-hd.png id=9 1024 x 1024 @ 16 bpp => 2048 KB
cocos2d: "blitz_kurz.png" rc=1 name=(null) id=12 50 x 50 @ 32 bpp => 9 KB
cocos2d: "gameover.png" rc=8 name=gameover-hd.png id=7 1024 x 2048 @ 32 bpp => 8192 KB
cocos2d: "home.png" rc=32 name=home-hd.png id=4 2048 x 2048 @ 16 bpp => 8192 KB
cocos2d: "particleTexture.png" rc=2 name=(null) id=11 87 x 65 @ 32 bpp => 22 KB
cocos2d: "stern.png" rc=2 name=(null) id=2 87 x 65 @ 32 bpp => 22 KB
cocos2d: "clownmenu.png" rc=60 name=clownmenu-hd.png id=1 1024 x 2048 @ 32 bpp => 8192 KB
cocos2d: CCTextureCache dumpDebugInfo: 13 textures using 60.1 MB (紋理總共佔用的內存大小!!!)
複製代碼

 上面包含了非常多有用的信息。紋理的大小、顏色深度(bpp)和每一個被緩存的紋理在內存中所佔用大小等。這裏的“rc”代表紋理的“引用計數”。如果這個引用計數等於1或2的話,那麼意味着,這個紋理當前可能不會需要使用了,此時,你可以放心地把它從紋理cache中移除出去。

你只移除你知道在當前場景下不太可能會被使用的紋理(即上面介紹的引用計數爲1或2的情況),這是一個明智的做法。另外,只移除那些佔用內存大的紋理。如果一個紋理只佔幾個kb的內存,其它移不移除都沒什麼太大的影響。(譯註:這就和程序優化一樣,不要做過多的細節優化,不要過早優化,要找到性能的瓶頸,然後再重點優化,以20%的時間換取80%的效率。過早和過多細節優化對於大多數程序而言,是需要極力避免的)。

 

SpriteFrames retain textures!

上面提到的例子中,紋理的引用計數可能有點讓人看不懂。你會發現,紋理集有很高的retain count,即使你知道這些紋理集中的紋理當前並沒有被使用。

你可能忽略了一件事:CCSprteFrame會retain它的紋理。因此,如果你使用了紋理集,你要完全移除它不是那麼容易。因爲,由這個紋理集產生的sprite frame還是保留在內存中。所以,你必須調用CCSpriteFrameCache的removeSpriteFramesFromTexture方法,能徹底清除紋理緩存中的紋理集。(譯註:記住,不是你調用對象的release方法了,對象的內存就會被釋放掉,而是引用計數爲0了,內存纔會被刪除)

[[CCSpriteFrameCache sharedSpriteFrameCache] removeSpriteFramesFromTexture:uncachedTexture];

 你也可以使用 removeSpriteFramesFromFile,並指定一個紋理集的.plist文件來清除緩存起來的精靈幀(spriteframes).

 

 

添加 SpriteFrames 非常耗時, 每次都是!

Note: 這一點只針對cocos2d v1.0有效,而cocos2d v2.x在加載之前會預先判斷。

這樣看起來有點無知(innocent):

[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"ui.plist"];

減少你的程序的大小

把紋理的顏色位深度減少到16位,不僅可以減少內存壓力,還可以有效地減少程序的體積。但是,我們還有其它方法可以更進一步地減少程序的大小。

 

TexturePacker PNG 圖片優化

如果你有某些原因,讓你堅持要使用PNG文件格式而不是我之前極力向你推薦的pvr.ccz文件格式,那麼TexturePacker有一個選項,叫做“Png Opt Level”(Png優化級別),可以幫助我們減少png文件的大小(注意:這樣並不會影響圖片加載時間)

就我目前的理解來看,最大的優化級別可以生成最小的文件大小。但是,它有一個缺點,就是非常耗時。對於2009年出的27寸的iMac來說,處理尺寸稍大的紋理,需要耗費10-20的時間來處理。由於該優化過程採用了多線程的方式,所以,如果你有機器是四核的,那麼速度應該會快一些。

當然,你只有在真正發佈應用的時候才需要利用這個優化特性。現在的問題是,它到底可以減少多少文件體積呢?

我最大的一張png圖片從2.4MB減少到了2.2MB.小一些的紋理從180kb減至130kb。可能單個文件減少的量並不是很多,可是當你的png圖片的總大小有18MB時,它可以使之減少至16MB。

注意,在xcode裏面有一項設置,你可能會把它忽略掉。你需要關閉"Compress PNG files"開關,因爲這個選項有可能會使你的png圖片膨脹。你可以在xcode的build settings裏面設置,如下所示:

如果激活此png壓縮選項,xcode會在png文件打包進程序的時候運行自帶的png優化程序。所以,有可能會使我們先前使用TP優化過的png圖片再次膨脹。因此,再次確保這個選項已關閉!

不過即使你沒有禁用此選項,你的程序大小還是會有所減小。因爲,你有可能使用一些沒有被TP優化過的png圖片。

 

檢查你的程序在App Store 裏面的大小

在Xcode裏面,運行Archive build(在菜單中選擇Product->Archive)。當build成功的時候,Xcode的Organizer窗口會打開,然後你會看到一個“Estimate Size”(評估大小)的按鈕,可以用來估算你的應用程序大小:

移除未使用的資源文件

在開發遊戲的過程中,你會經常添加、移除和替換遊戲資源。所以,你可能會因爲某些原因,忘記移除一些不用的圖片資源。所以,你需要額外注意把它們都從項目中移除出去,至少要從程序的target中出去。

尤其是你使用多個target的時候(比如,你同時維護ipad和mac版本),你就極有可能會在一個target裏面添加一些錯誤的資源。

當然,在移除資源之後,你一定要充分測試你的遊戲。切記!一定要充分測試。

 

減少聲音文件大小

有時候,我們也會忽視這個問題。如果你不考慮聲音文件的格式,不管是就內存的使用還是程序的大小而言,都是一種極大的浪費。下面是一些方法可以用來減少聲音文件的大小。我推薦大家使用一款免費的聲音編輯工具

 

立體聲道變單聲道 – 你的mp3文件可以採用立體聲,但是,這樣做值得嗎?如果你聽不出來差別的話,建議還是採用單一聲道。這樣可以把文件大小和內存使用都減少一半。

MP3 比特率 –在iOS設備上面,任何比特率大於192kbps的聲音都是浪費。你可以儘量採用低的比特率來獲得最好的音質效果,這是一個折中。一般來說,96到128kbps對於mp3文件來說夠用了。

採樣率 – 大部分的聲音文件使用11,22,44,或者48kHz採樣率。採樣率越低,聲音文件越小。但是,這樣聲音質量也會越低。44kHz已經達到了CD的音質了,而48kHz會更好(這個差別只有調音師纔可以聽出來)

在大部分情況下,44kHz或者更高的比特率都有點浪費。所以,可以嘗試下減小採樣率(在Audacity裏面:Tarck->Resample)。不要只是修改採樣率,因爲這樣會改變聲音文件的音高。

 

Streaming MP3 Files

mp3文件的播放,首先是加載到內存中,然後解碼爲未壓縮的聲音buffer,最後再播放。

就我目前所知,CocosDenshion的SimpleAudioEngine的playBackgoundMusic是流式播放mp3文件的。流試處理有兩個優點:1.更小的內存足跡。2.解碼mp3文件採用ios硬件,而不是cpu。但是,硬件一次只能解碼一個文件,如果同時播放多個,那麼只有一個採用的是硬件解碼,其它的都是軟件解碼。

 

減少Tilemap大小

許多開發者沒有注意到,tilemap大小太大會消耗大量內存。假設你有一個1000*1000的tilemap,這個大概要消耗1M的內存--如果每一個tile消耗一個字節的內存的話。然而,如果每一個tile大概消耗64個字節的話,那麼這個tilemap就會消耗60MB內存。我的天啊!

除了寫一個更優的tilemap渲染器以外,我們唯一可以做的就是減少tilemap的大小了,也可以把地圖一分爲二。

 

就沒啦?

哈哈,是滴。這次,我把文章變短一些,希望你們都看懂了。:)

發佈了2 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章