首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> J2ME

J2ME 遊戲圖集分割實戰:setClip 與 Image.createImage 兩大方案深度對比

     編輯:J2ME

圖集分割的必要性

遊戲開發中將零散小圖(數字、精靈幀、UI 圖示)合併為單一大圖(Sprite Sheet),可減少 JAR 體積、降低類載入數量、提升載入速度。運行時需將大圖分割為獨立 Image 物件以供高頻繪製。

方案一:運行時 setClip 繪製(零額外記憶體)

不建立新 Image,每幀透過 setClip 只繪製大圖對應區域。

// 繪製第 3 個數字 (假設每個 10x15)
g.setClip(50, 50, 10, 15);
g.drawImage(numberSheet, 50 - 2*10, 50, Graphics.LEFT | Graphics.TOP);
g.setClip(0, 0, getWidth(), getHeight());
  • ✅ 無額外堆記憶體
  • ✅ 保留透明度(MIDP 1.0/2.0 皆可)
  • ❌ 每幀多次 setClip 呼叫,CPU 開銷較大

方案二:預分割為獨立 Image 陣列(繪製效能最佳)

Image[] digits = new Image[10];
Image sheet = Image.createImage("/res/digits.png"); // 100x15

for (int i = 0; i < 10; i++) {
    digits[i] = Image.createImage(10, 15); // 可變動圖片
    Graphics g = digits[i].getGraphics();
    g.drawImage(sheet, -i * 10, 0, Graphics.LEFT | Graphics.TOP);
}

關鍵陷阱:MIDP 1.0 透明像素遺失

Image.createImage(w, h) 建立的可變動圖片在 MIDP 1.0 上不支援透明通道,貼上含透明像素的源圖會導致透明區變黑/白。

三大補救方案對比

方案代碼相容性優點缺點
堅持 setClip見方案一全裝置零記憶體、保留透明繪製較慢
Nokia 專用 APIDirectUtils.createImage(w, h, 0)僅 Nokia效能佳、保留透明廠商鎖定
MIDP 2.0 標準 APIImage.createImage(src, x, y, w, h, transform)MIDP 2.0+標準、效能佳、保留透明需 MIDP 2.0

推薦策略:運行期檢測自動選擇

public static Image[] splitSheet(Image sheet, int cols, int rows, int fw, int fh) {
    Image[] frames = new Image[cols * rows];
    boolean isMIDP2 = System.getProperty("microedition.profiles").contains("MIDP-2");
    boolean isNokia = System.getProperty("microedition.platform").toLowerCase().contains("nokia");

    for (int r = 0; r < rows; r++) {
        for (int c = 0; c < cols; c++) {
            int idx = r * cols + c;
            int sx = c * fw, sy = r * fh;

            if (isMIDP2) {
                // 標準 MIDP 2.0 方案(最佳)
                frames[idx] = Image.createImage(sheet, sx, sy, fw, fh, Sprite.TRANS_NONE);
            } else if (isNokia) {
                // Nokia MIDP 1.0 方案
                try {
                    Class du = Class.forName("com.nokia.mid.ui.DirectUtils");
                    java.lang.reflect.Method m = du.getMethod("createImage", int.class, int.class, int.class);
                    frames[idx] = (Image) m.invoke(null, fw, fh, 0); // 0 = 透明
                    Graphics g = frames[idx].getGraphics();
                    g.drawImage(sheet, -sx, -sy, Graphics.LEFT | Graphics.TOP);
                } catch (Exception e) {
                    // 回退 setClip 方案
                    frames[idx] = null; // 標記需用 setClip
                }
            } else {
                // 通用回退:標記需用 setClip
                frames[idx] = null;
            }
        }
    }
    return frames;
}

繪製時統一處理

void drawFrame(Graphics g, Image[] frames, int index, int x, int y) {
    Image img = frames[index];
    if (img != null) {
        g.drawImage(img, x, y, Graphics.LEFT | Graphics.TOP);
    } else {
        // 回退 setClip 方案(需知道源座標)
        int fw = 10, fh = 15; // 已知幀尺寸
        int sx = (index % 10) * fw;
        g.setClip(x, y, fw, fh);
        g.drawImage(sheet, x - sx, y, Graphics.LEFT | Graphics.TOP);
        g.setClip(0, 0, getWidth(), getHeight());
    }
}

總結

現代 J2ME 開發(MIDP 2.0+)應優先使用 Image.createImage(src, x, y, w, h, transform) 進行標準化分割;維護舊專案(MIDP 1.0)時,採用運行期檢測 + 多方案回退策略,可在保證相容性的前提下最大化效能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved