作者分享《Death Flight》開發過程中「編碼比預想快」的關鍵:學習階段預先搭好框架。本文詳細拆解主 MIDlet 類別 Flight 如何統籌整個遊戲,以及 J2ME 圖形體系(Displayable、Canvas、GameCanvas、Layer、TiledLayer、Sprite)在專案中的具體應用與封裝策略。
Flight (MIDlet)
├── Display display
├── Score score (RMS 高分)
├── int scorevalue (當前分數)
├── MainMenu mainmenu (extends List)
├── HighScoreScreen highscorescreen (extends Form)
├── GameLoop Game (extends GameCanvas)
└── 協調方法:startGame/showHighScore/showMainMenu/getScore/addHighScore/showHelp
public class Flight extends MIDlet {
protected Display display;
protected Score score;
protected int scorevalue;
private MainMenu mainmenu;
private HighScoreScreen highscorescreen;
private GameLoop Game;
public Flight() {
display = Display.getDisplay(this);
score = new Score("HallOfFame");
mainmenu = new MainMenu(this);
highscorescreen = new HighScoreScreen(this, score);
}
protected void startApp() { showMainMenu(); }
protected void pauseApp() {}
protected void destroyApp(boolean u) { System.gc(); notifyDestroyed(); }
// 畫面切換統一入口
protected void startGame() {
Game = new GameLoop(this); // 每次新建,確保狀態重置
Game.start(); // 啟動 GameCanvas 內建執行緒
display.setCurrent(Game);
}
protected void showMainMenu() { display.setCurrent(mainmenu); }
protected void showHighScore() { highscorescreen.init(); display.setCurrent(highscorescreen); }
protected void getScore() { scorevalue = Game.getScore(); }
protected void addHighScore(int v) {
if (highscorescreen.isHighScore(v))
display.setCurrent(new AddHighScoreScreen(this, v));
}
protected void showHelp() {
Alert a = new Alert(null, "按#鍵上飛,否則下墜…", null, AlertType.INFO);
a.setTimeout(5000);
display.setCurrent(a, mainmenu); // 5秒後自動回主選單
}
protected void Quit() { destroyApp(true); }
}
Flight 統一,避免類別間循環依賴。startGame() 每次 new GameLoop(),天然解決「重玩狀態殘留」問題。destroyApp 呼叫 System.gc(),釋放大量圖片資源,減少 OOM 風險。display.setCurrent(alert, nextScreen) 實現「提示→自動返回」無需額外執行緒。| 類別 | 用途 | 專案中的實例 |
|---|---|---|
Canvas | 低階繪圖、遊戲主畫面 | —(改用 GameCanvas) |
GameCanvas | 雙緩衝、按鍵狀態查詢、遊戲迴圈 | GameLoop |
Screen 子類 | UI 表單、選單、輸入 | MainMenu(List), HighScoreScreen(Form), AddHighScoreScreen(Form) |
Alert | 暫時性提示 | 幫助畫面、錯誤提示 |
javax.microedition.game)Layer (抽象基類)
├── LayerManager (管理多層:可見性、Z-order、位置)
├── TiledLayer (格網圖層:小圖塊組成大場景,支援動態修改單元)
│ └── Terrain (本專案擴展:動態生成地形/障礙、碰撞檢測、分數計算)
└── Sprite (精靈:動畫幀、翻轉、碰撞矩形)
└── GameObject (封裝:生命週期、幀率控制、自動播放)
└── Helicopter (組合:機身 + 螺旋槳 + 爆炸特效)
setCell() + 下標陣列滾動極高效,無需手動 drawImage 迴圈。nextFrame() + paint() 硬體加速(部分裝置)。append(),渲染順序自動管理。Score extends BaseRMS,封裝 RecordStore 讀寫,提供:
getNames()/getValues() → 高分顯示updateScores(score, name) → 冒泡排序插入前 3 名isHighScore(score) → 判斷是否彈出輸入名字畫面詳見後續文章《記錄存儲》與《RMS 從入門到精通》。
TiledLayer 使用活動下標(indexMap[])實現卷軸,曾「纏很久才弄對」。Flight MIDlet 展示了「單一職責、集中調度、狀態無殘留、資源顯式管理」四大工程原則在 J2ME 環境下的落地。配合 GameCanvas + Layer 體系,開發者可將精力集中在遊戲邏輯(Terrain、Helicopter)而非底層繪圖迴圈。這套架構在當時屬於「輕量級商業遊戲標準範本」,至今對理解現代遊戲引擎(Scene Graph、Entity-Component、Game Loop)仍具啟發價值。