受限於早期功能機記憶體與檔案系統限制,將數十個小圖片合併為單一大圖片 (Sprite Sheet / Texture Atlas) 是 J2ME 遊戲開發的標準做法。Graphics.setClip() 提供了高效的子圖提取與渲染機制。
| 策略 | 原理 | 優點 | 缺點 |
|---|---|---|---|
| 運行時 setClip 繪製 | 每幀計算源矩形,drawImage(atlas, -srcX, -srcY, anchor) | 無額外記憶體、動態裁剪靈活 | 每幀重複裁剪計算、透明度處理較慢 |
| 預先分割快取 | 啟動時 createImage(w,h) + drawImage 生成 Image 陣列 | 渲染極快、邏輯簡單、支援像素級操作 | 佔用堆記憶體、MIDP 1.0 易丟失透明通道 |
private Image[] imgNumbers = new Image[10]; // 0-9 數字精靈
private void initImgNumbers() throws IOException {
Image atlas = Image.createImage("/res/number_atlas.png"); // 100x15 像素
Graphics g;
for (int i = 0; i < 10; i++) {
imgNumbers[i] = Image.createImage(10, 15); // 單個數字 10x15
g = imgNumbers[i].getGraphics();
// 從圖集複製對應區域:X 偏移 -i*10,Y 偏移 0
g.drawImage(atlas, -i * 10, 0, Graphics.TOP | Graphics.LEFT);
}
}
// 遊戲主迴渲染
public void paint(Graphics g) {
g.drawImage(imgNumbers[currentDigit], x, y, Graphics.TOP | Graphics.LEFT);
}
根因:MIDP 1.0 `createImage(w,h)` 建立的可變圖片不支援 Alpha 通道,`drawImage` 複製時透明像素變黑。
| 方案 | 適用場景 | 程式碼 |
|---|---|---|
| 方案 A:運行時 setClip | 所有 MIDP 1.0 裝置 | g.setClip(x, y, w, h); g.drawImage(atlas, x - srcX, y - srcY, anchor); |
| 方案 B:Nokia 專有 API | Nokia S40/S60 系列 | img = DirectUtils.createImage(w, h, 0x00000000); // ARGB=0 透明背景 |
| 方案 C:手動像素複製 | 通用但效能差 | getRGB() → 過濾透明 → createRGBImage() |
// 白色圖集 + setColor + drawImage 實現跑馬燈/閃爍/受擊閃白
g.setColor(0xFF0000); // 紅色濾鏡
g.drawImage(whiteAtlasSprite, x, y, anchor);
// 旋轉/縮放 (MIDP 2.0 Sprite 類)
Sprite sprite = new Sprite(atlas, frameW, frameH);
sprite.setTransform(Sprite.TRANS_ROT90); // 90度旋轉
sprite.paint(g);
掌握 `setClip` 與圖集分割技術,是 J2ME 遊戲開發者在受限資源下實現豐富視覺效果的核心基本功。雖然智慧機時代已終結 J2ME 平台,但這些圖形渲染優化思想在嵌入式 GUI、物聯網裝置開發中依然具備參考價值。