初寫 J2ME 遊戲時若未考慮移植,後期適配將極其痛苦。預先規劃可移植架構,將平台差異隔離封裝,是高效跨機型開發的核心。本文從螢幕適配、API 差異、按鍵映射、庫封裝四大維度,分享實戰經驗。
關鍵在於「控件尺寸參數化」與「繪製邏輯解耦」。
常見需求:圖片裁切、像素級操作、全螢幕模式。MIDP 1.0 缺乏,廠商擴充 (Nokia UI) 或 MIDP 2.0 提供。
策略:定義統一介面,平台特定實現分離。
// 統一介面
public static Image createSubImage(Image src, int[] rect); // rect: x,y,w,h
// Nokia UI 實現
public static Image createSubImage(Image src, int[] r) {
Image dst = DirectUtils.createImage(r[2], r[3], 0);
dst.getGraphics().drawImage(src, -r[0], -r[1], Graphics.TOP | Graphics.LEFT);
return dst;
}
// MIDP 2.0 實現
public static Image createSubImage(Image src, int[] r) {
return Image.createImage(src, r[0], r[1], r[2], r[3], Sprite.TRANS_NONE);
}
遊戲邏輯只呼叫 createSubImage(),移植時替換實現類即可,零修改業務代碼。代價:增加一次間接呼叫,效能微損,但換來極大維護性收益。
MIDP 提供 getGameAction() 但僅覆蓋方向/確認/軟鍵,遊戲常需更多鍵 (數字鍵、*、# 等)。
方案:
keyState,每 bit 代表一虛擬鍵狀態 (1=按下)keyPressed/Released 更新對應 bitmapKeyCode(int keyCode) -> int virtualKeyBit 映射函數,**每機型專屬實現**(keyState & VIRTUAL_KEY_FIRE) != 0進階:虛擬鍵之上再定義 Game Action,支援玩家自訂按鍵配置。
將所有平台差異集中在三個類,移植新機型只需重寫這三類:
| 類別 | 職責 | 封裝差異點 |
|---|---|---|
| GameFramework | 遊戲主迴圈、渲染排程、輸入處理、跨平台工具方法 | 執行緒模型、螢幕刷新策略、系統事件處理 |
| GraphicsManager | 圖片載入/切割/旋轉/繪製、動畫管理 (類 Sprite) | 圖片建立 API、透明度支援、硬體加速可用性 |
| UIComponent | 所有遊戲內 UI 控件 (選單、對話框、HUD...) | 字型渲染、觸控/按鍵交互、全螢幕模式切換 |
輔以 所見即所得動畫/圖片編輯工具,美術資源直接匯出資料檔,程式碼零修改載入。
採用此架構,從 Motorola V600 移植到 Nokia N-Gage **僅耗 1 分鐘** (替換三個類的實現檔)。
移植本質是「拆合」:將差異點拆出、隔離、標準化介面。核心三步:參數化 UI、介面化 API、虛擬化輸入。但真正的挑戰在於不可預期的機型 Bug,養成「預留擴展點、詳盡測試矩陣」的習慣,才能在碎片化 J2ME 生態中生存。