二. 示例:九宮格(TICTACTOEMIDLET)
1、設計
概述
這個示例應用程序是一個簡單的MIDlet,允許游戲者與MIDlet程序之間玩一種稱為九宮格的人機游戲。這個例程說明:
使用高級和低級用戶界面組件
在多顯示屏幕之間進行切換
處理簡單的命令
動態適配顯示尺寸
處理鍵盤事件
游戲者首先選擇使用哪種棋子(用圓和叉表示),然後開始游戲。游戲者和MIDlet誰是先手是隨機決定的。每走一步棋之後,程序都要檢查游戲狀態,判斷游戲是否已經結束。游戲的幾種可能結果是:游戲者贏,MIDlet程序贏,或者平局。在應用程序運行期間,雙方的得分都能顯示出來。游戲者可以隨時開始新游戲或者退出游戲。
圖2:所示的屏幕快照是游戲中的MIDlet用戶界面。
圖2:游戲屏幕的先後順序
2、九宮格MIDlet
下面是九宮格MIDlet的類模式圖:
圖3:九宮格MIDlet類圖
當MIDlet啟動方法startApp()時,將創建閃爍屏幕和第一個游戲屏幕(ChoosePieceScreen)。閃爍屏幕顯示4秒之後,第一個游戲屏幕開始顯示。ChoosePieceScreen讓游戲者選擇使用哪種棋子(圓還是叉)。當游戲者做出選擇之後,他可以使用OK鍵確認。這會使ChoosePieceScreen回調主MIDlet的choicePieceScreenDone()方法。
ChoosePieceScreen是使用高級應用編程接口List類實現的。
圖4:ChoosePieceScreen是一個高級用戶界面List子類
choosePieceScreenDone()回調創建並顯示下一個屏幕,這個屏幕在此應用程序中作為游戲的主屏(GameScreen)。
每當輪到游戲者下棋的時候,游戲者使用GameScreen的箭頭鍵和Select按鈕來選擇想要走的空格。每一回合之後,應用程序都會檢查游戲的狀態,檢查其是否符合游戲結束條件並顯示游戲結果。游戲者通過點擊GameScreen的Quit命令結束游戲,或使用New命令開始新一輪游戲。Quit(結束)命令調用TicTacToeMIDlet的quit()方法,然後MIDlet就會調用destroyApp()方法來終止整個MIDlet程序。
游戲程序邏輯被封裝在一個單獨的Game類中。本文只關注MIDlet的圖形設計,而對游戲程序邏輯不作深入探討。如果要與現有的applet Java程序作比較,請參閱http://java.sun.com/applets/jdk/1.0/demo/TicTacToe/TicTacToe.java 和http://java.sun.com/products/jfc/tsc/articles/tictactoe/index.html 中的游戲程序邏輯。
GameScreen通過使用低級Canvas和Graphics類來實現。它使用Canvas、Image和Graphics對象來繪制圖形。
GameScreen首先初始化基於畫布尺寸的顯示面板。這可讓MIDlet能夠運行在不同顯示屏幕的移動設備上。在本例中還使用了一個Image對象用來表示游戲面板。然後GameScreen根據游戲者在ChoosePieceScreen中所做的選擇為游戲者和MIDlet分配棋子。游戲然後進行初始化(包括隨機決定誰是先手),然後游戲就開始了。
為了使GameScreen能夠被移植,MIDlet的鍵盤代碼必須被映射到游戲動作上,如:Up、Down、Left、Right和Fire,用於具有不同鍵盤的移動設備。每當一個鍵被按下的時候,keyPressed()方法就會判斷這是一個方向鍵還是一個Fire/Select鍵。如果按下的鍵是方向鍵,光標就會相應地移動,幫助游戲者可視化地選擇一個空格放入棋子。Select鍵用來選擇一個空格放入棋子。如果探測到滿足游戲結束的條件,就會顯示一條信息宣布游戲的獲勝者和本輪游戲的得分。(見下圖)
圖5: GameScreen 是一個低級 Canvas(畫布)子類
3、TicTacToeMIDlet.java
TicTacToeMIDlet非常簡單:它處理MIDlet的生命周期事件。它根據需要創建屏幕對象並且處理來自屏幕的回調。ChoosePieceScreenDone回調被用來創建GameScreen。quit方法則被GameScreen用來結束游戲。
package example.tictactoe;
import java.io.IOException;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
public class TicTacToeMIDlet extends MIDlet {
private ChoosePieceScreen choosePieceScreen;
private GameScreen gameScreen;
public TicTacToeMIDlet()
{
}
public void startApp() {
Displayable current = Display.getDisplay(this).getCurrent();
if (current == null) {
// first time we've been called
// Get the Logo image
Image Logo = null;
try
{
Logo = Image.createImage("/tictactoe.png");
}
catch (IOException e) {
// just use null image
}
Alert splashScreen = new Alert(null, "Tic-Tac-Toe\nForum Nokia", Logo, AlertType.INFO);
splashScreen.setTimeout(4000);
// 4 seconds
choosePieceScreen = new ChoosePieceScreen(this);
Display.getDisplay(this).setCurrent(splashScreen, choosePieceScreen);
}
else
{
Display.getDisplay(this).setCurrent(current);
}
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void quit()
{
destroyApp(false);
notifyDestroyed();
}
public void choosePieceScreenDone(boolean isPlayerCircle)
{
gameScreen = new GameScreen(this, isPlayerCircle);
Display.getDisplay(this).setCurrent(gameScreen);
}
}