PNG 是 J2ME 遊戲最常用的圖片格式。圖片資源的大小、儲存方式直接影響 JAR 體積與執行時記憶體佔用。本文分享實務中驗證的兩種優化策略:大圖集分塊載入 與 二進位資源包合併。
將同一遊戲階段所需的所有小圖合併為一張大圖(圖集),程式以 Graphics.drawRegion() 或像素陣列切割繪製。優點:減少檔案頭開銷、利用 PNG 壓縮相似像素、減少 Image.createImage() 呼叫次數。
若將所有階段(選單、遊戲、排行榜)合為一張超大圖,進入選單時仍會載入遊戲階段圖片,造成記憶體浪費。解決方案:分階段建立多張圖集。
menu.png:選單背景、按鈕、標題等game.png:角色、敵人、地圖塊、UIrank.png:排行榜背景、字體、圖示狀態切換時:menu.png → null + System.gc() → 載入 game.png。確保同一時間僅佔用當前階段所需記憶體,避免 OutOfMemoryError。
小團隊常缺乏成熟圖集工具,直接放置大量獨立 PNG。實測:21 張 14×14 PNG 獨立存放 vs 合併為單一二進位檔(無額外壓縮),後者 JAR 體積 減少約 10 KB。主要省下:每個 PNG 的檔案頭、IHDR/IDAT/IEND 區塊、CRC、目錄項開銷。
resources.dat:
// 簡易格式範例
[檔案數: short]
重複 每個檔案:
[檔名長度: byte][檔名: bytes]
[資料長度: int][PNG 原始位元組: bytes]
resources.dat 至 byte[] 或 ByteArrayInputStream。Image.createImage(byte[], offset, len)。null + System.gc() 釋放。| 維度 | 圖集法 | 二進位包法 |
|---|---|---|
| 引擎需求 | 需支援 drawRegion/像素切割 | 無特殊需求,標準 API 即可 |
| 記憶體粒度 | 整張圖集常駐 | 可逐張釋放,更細緻 |
| JAR 體積 | 極佳(PNG 壓縮跨圖) | 良好(省去檔案結構開銷) |
| 實作難度 | 需美術配合切圖座標 | 僅需打包工具,美術流程不變 |
未來文章將探討動畫系統、地圖編輯器等實務主題。