■應用程序及其規格
Java ME 開發環境與桌面及服務器應用程序的運行環境不同,API 中規定了各類設備的 Java 虛擬機器規格,這些規格定義為“配置”和“ 配置文件”的組合。(根據需要可以追加“擴展配置文件”)
規格 = 配置 + 配置文件 ( + 擴展配置文件)
開發人員在配置中定義基本的 Java 虛擬機器規格及類庫的最小集,而配置以 JCP 為標准,主要有以手機為例的 CLDC (Connected Limited Device Configuration) 和以嵌入式機器為例的 CDC (Connected Device Configuration);配置文件用於定義特定類別的(手機、 PDA 等)、面向機器的 API,其他附加部分則定義在擴展配置文件中。作為 MIDP (Mobile Information Device Profile) 配置文件的標准集 ,CLDC 在移動電話領域得到了廣泛應用。
舉例來說:開發面向日本市場的手機 Java 應用程序時,它的規格是配置和配置文件的組合,如下所示。( ) 表示各種規格的版本:
手機運營商 規格組合 NTT DoCoMo i 應用服務 CLDC (1.0 或 1.1) + DoJa 配置文件 au 開放式應用服務 CLDC (1.1) + MIDP (2.0) SoftBank S! 應用服務 CLDC (1.0 或 1.1) + MIDP (1.0 或 2.0) + JSCL/MEXANTT DoCoMo 的 DoJa 配置文件是指 NTT DoCoMo 面向 FOMA 定制的規格,有很多版本。SoftBank 的 JSCL/MEXA 是指面向 SoftBank 終端 定制的、可以根據實際需要進行擴展的規格,即所謂的“擴展配置文件”。
本文介紹的游戲基於 CLDC 1.1 + MIDP 2.0 的應用服務。
■使用 API 創建游戲
在本例中,2.0 兼容應用程序采用了面向游戲開發的 API,收錄在 Java 程序包 javax.microedtion.lcdui.game 中。該游戲程序包,即用 戶接口提供的類定義如下:
GameCanvas 提供游戲用戶界面基礎。 Layer 表示游戲中視覺要素的抽象類。下面的 Sprite、TiledLayer 繼承這個 Layer 的特性。 LeyerManager 管理一系列 Layer。 Sprite 游戲的基本要素,由一個或數個圖像組合描述而成。組合數個圖像時、每個圖像分別用一個類似電影的鏡頭來表示,因此將所有圖 像組合起來後能夠表現角色的動作。 TiledLayer 就像平鋪式鋪滿的地板一樣,用分割的帖圖可以表現畫面要素。具體來講,就是用 TiledLayer 可以表現游戲的背景及游戲的結構 件。■游戲生成器
游戲生成器由場景、平鋪層、動畫層組成,可以在圖形環境中編輯上面的 LayerManager、TiledLeyer、Sprite。
圖1 游戲生成器設計畫面
要在游戲的場景和角色中使用 Sprite 和 TiledLayer,可以用游戲生成器將背景、角色和結構件等部分編寫到圖形中。劇本和人物動作等 這些游戲操作內容必須全部通過 Java 程序描述。大致的作業流程基於以下事項:
准備背景和角色原型的圖像文件
將圖像文件導入到游戲生成器中
在游戲生成器的 GUI 環境中創建平鋪層和動畫層
通過游戲生成器結合平鋪層和動畫層,以創建場景
設計角色動作及游戲推進等程序
假設游戲生成器要使用 API 中說明的平鋪層、動畫層的 GameCanvas 類或者 GameCanvas 擴展類。游戲生成器將編輯後的結果全部保存在 Java 類中,同時自動生成平鋪層和動畫層的 getter 方法並將其保存在類中。調用此獲取方法可以生成平鋪層和動畫層的實例並返回給調用源 ,因此可以使用 GameCanvas 類的實例獲取方法來得到對象。最後,可以從繼承 MIDlet 類的主程序(確切來講相當於包含 Java SE 的 main 方法的類)中調用這個 GameCanvas (繼承)類時,游戲應用程序的開發就大功告成了。
游戲生成器創建、保存的類的源代碼,大多數只能用來做參考。您可以通過游戲生成器對它進行修改,我們為您預留了可以編輯直接代碼來 追加特定處理的地方。
要通過 NetBeans 打開游戲生成器,需要創建 MIDP 應用程序項目,並在項目中創建新的視覺游戲設計圖。實際試用的時候打開樣例項目比 較好,從主菜單選擇樣例項目的方法:“文件”>“新建項目”>“樣例”>“Mobility”>“MIDP”>“通過游戲生成器創建的 簡單游戲”,這樣就可以打開游戲生成器了。
接下來,我們按順序來看看這 5 個作業的概要。
■准備和導入圖像文件
將 1 和 2 結合起來說明。
圖 2 用做素材的圖像文件
在游戲生成器中創建平鋪層和動畫層時,需要使用嵌入平鋪層中的圖像和用作動畫層幀的角色圖像。比如說,NetBeans 中預留的示例圖像 文件含有縱橫方向單位為 16*16 像素的背景、建築物和角色,它們可以作為最基本的部件在游戲生成器中使用。在游戲生成器中導入圖像時, 需要指定分割圖像的縱橫像素值,因此在導入上面的圖像時,如果指定為 16 像素,如下圖所示,圖像將被分割為 16*16 大小的貼圖導入到游 戲生成器中,然後可以將各個貼圖作為獨立的部件使用。
圖 3 導入到游戲生成器中的圖像文件
在 Java 程序中處理平鋪層(TiledLayer 類)和動畫層(Sprite 類)時,這些經過分割的帖圖將被賦予索引編號,我們可以通過索引編號 來訪問它們。比如在上圖中,左上角茶色帖圖的索引編號是“1”,而第一行中間位置上的紅色屋頂圖像可以通過索引編號“9”來訪問。索引 編號“0”表示圖像未被賦予任何職能。
■在游戲生成器中的 GUI 環境中創建平鋪層和動畫層
步驟 3:分別指定平鋪層和動畫層的相關內容。
平鋪層
在平鋪層的編輯畫面,可以配置各個讀入圖像的部件。在下圖中,中間是平鋪層的編輯畫面,其下方列出了利用讀入圖像生成的平鋪層的索 引編號,左下方是當前圖層的信息。
圖 4 平鋪層的編輯畫面
在平鋪層中,可以通過“准備和導入圖像文件”中說明的索引編號來訪問圖像,平鋪層的信息由游戲生成器保存在 2 維整數數組中。下例 表示將索引編號為“7”的圖像粘貼到平鋪層的第 1 行和第 1 列中(平鋪層的行、列編號從 0 開始)。同樣,將索引編號為“16”的圖像粘貼 到第 1 行、第 3 列中。
int tiles[][] = {
{ 7, 3, 17, 6, 6, 6, 6, 35, 23, 16, 16, ... }
{ 7, 3, 5, 16, 16, 16, 16, 16, 26, 16, ...}
....
{16, 16, ..... }
};
在 Java 程序中,TiledLayer 采用如下所示的結構。
TiledLayer tl = new TiledLayer(colums, rows, image, tileWidth, tileHeight);
/*
int columns : 圖層的列數(圖層上橫向排列的平鋪數量)。列編號從 0 開始。
int rows : 圖層和行數(圖層上縱向排列的平鋪數量)。行編號從 0 開始。
Image image : Image 類提供的圖像文件對象
int tileWidth : image 類中的平鋪層的橫向寬度(像素)
int tileHeight : image 類中的平鋪層的縱向高度(像素)
*/
如下所示,在平鋪層 tl 右上方的帖圖(第 0 行 第 0 列)中配置紅色屋頂的房子時(圖像文件的索引編號為 9),可以使用 setCell() 方 法來定義平鋪層的圖像:
tl.setCell(0, 0, 9); // 將索引編號為“9”的圖像復制到平鋪層的第 0 行和第 0 列中
如下所示,游戲生成器自動生成平鋪層的獲取方法並將其保存在類中〔下面的 getMyImage() 方法用於讀入圖像文件並充當 Image 對象的 返回方法〕。
public TiledLayer getMyTiledLayer() throws java.io.IOException {
if (MyTileLayer == null) {
MyTileLayer = new TileLayer(24, 23, getMyImage(), 16, 16);
int tiles[][] = {
{ 7, 3, 17, 6, 6, 6, 6, 35, 23, 16, 16, ... }
{ 7, 3, 5, 16, 16, 16, 16, 16, 26, 16, ...}
....
{16, 16, ..... }
};
for (int row = 0; row < 23; row++) {
for (int col = 0; col < 24; col++) {
tl.setCell(col, row, tiles[row][col]);
}
}
}
return myTiledLayer;
}
還可以在圖層中嵌入動畫,顯示動畫的圖層叫做“動畫層”。比如說,准備好以下圖像,然後將各個圖像定義為幀之後就可以實現燈光火焰 搖曳的情景。
圖 5 燈光的火焰
以紙質筆記本上的“翻頁動畫”塗鴉為例,繪制在每張紙上的畫就相當於 1 個幀。游戲生成器可以通過設置幀來創建動畫,如下所示,將 每個圖像都當做 1 個幀並且按順序粘貼起來,這樣便可以實現動畫效果。下面的圖像有點不好解釋,但上面的 4 個圖像按從左到右的順序配 置後,用 200ms 的速度來切換圖像,就可以表現出進行此類編輯的情形。按下播放鍵一邊確認一邊繼續編輯。完成後的動畫(這裡就是指搖曳 的燈火)可以配置在平鋪層的任何位置。
圖 6 編輯動畫層
在程序中,這個動作也是通過使用索引編號訪問來實現。如下所示,創建一個單維數組,其中保存了圖像各幀的索引編號(假設火焰各張圖 像的索引編號從右到左依次為:89、90、91、92),然後將這個數組傳遞給 TiledLayer 類的 createAnimatedTile() 方法,此平鋪層的索引編 號就重新分配並且做為返回值返回。
int[] AnimTorchSequence001 = {89, 90, 91, 92};
// tl 是 TiledLayer 類的實例
int AnimTorch = tl.createAnimatedTile(AnimTorchSequence001[0]);
如果在定義平鋪層的 2 維數組中使用此平鋪層的索引編號 (上例中為返回到 AnimTorch 的整數) ,那麼就可以創建包含動畫平鋪的平鋪層 。
int tiles[][] = {
{ 7, 3, 17, 6, AnimTorch, 6, 6, 35, 23, 16, 16, ... }
{ 7, 3, 5, 16, 16, 16, 16, 16, 26, 16, ...}
....
{16, 16, ..... }
};
在上例中,我們定義了 200ms 的顯示間隔,這個顯示間隔僅僅做為游戲生成器創建的靜態值保存在用於實際控制游戲的類中。這個顯示間 隔沒有硬性規定必須在游戲生成器中定義,但是,如果以後游戲生成器擴展的話,它可能做為實際顯示代碼的一部分使用。
動畫層
使用游戲生成器創建動畫層和上面創建動畫平鋪的方法大體相同。首先創建相當於游戲角色的動畫層,這樣便可以在動畫層中定義相應角色 的復數動畫。比如下面的圖像是 NetBeans 提供的示例,它用一個個鏡頭表現角色的動作:第 1 行向下行走、第 2 行向上行走、第 3 行左右 行走。事先准備好這些圖像,並在動畫層中將其設置為幀,就可以准備好游戲中上場的角色了。在程序中調用創建好的動畫層和動畫層中定義 的動畫,就可以讓角色沿各個方向移動,或者做出特定動作。
圖 7 行走的角色
游戲生成器只能保存動畫層幀的信息,將其做為包含索引編號的單維數組,動畫層的動畫對角色實際的動作信賴性很大。目前的游戲生成器 雖然可以定義動畫層,但無法定義畫面中動畫層的動作,而單維數組是用來表示被保存的幀的推進的,如何使用這個數組,只能交由用戶處理 。
■使用游戲生成器將平鋪層和動畫層組合起來創建場景
步驟 4。
將創建好的平鋪層和動畫層組合起來就可以做成場景了。最簡單的場景擁有一個平鋪層和一個動畫層,此時,平鋪層就是背景,可以實現角 色在一個背景下的動作。但更多情況下,場景由多個平鋪層重疊而成。比如,角色向下行走時,如果遇到樹木就就不能前進了,像這種設置障 礙物的情況也是常有的。這時,預先在別的圖層中定義障礙物,程序處理就變得簡單多了。比如在下圖中,一個場景“Forest”由 4 個平鋪層 組合而成,游戲者看到的是“Forest”畫面,而它內部卻是由 Things、Trees、Water 這3個圖層疊加而成。
圖 8 重疊數個圖層來制作場景
程序是用來描述操作和處理的,比如說角色與“Trees”圖層的圖像重疊時的處理,或者角色與“Water”重疊時的處理等,因此可以描述角 色走近水池和撞到樹等動作。更具體一點來說,Sprite 類提供了一個 collidesWith() 方法,我們假設角色叫托馬斯(Thomas),那麼程序就可 以描述“托馬斯與平鋪層 Trees 的圖像發生沖突時的處理”。
...
private Sprite spriteThomas; //一個叫“托馬斯”的角色
private TiledLeyer tlTrees; // 平鋪層「Trees」
...
if (this.spriteThomas.collideswith(this.tileLayerTrees, true) {
// 托馬斯與平鋪層 Trees 的圖像發生沖突時的處理
...
}
...
下圖展示了如何通過游戲生成器創建場景。在確認平鋪層以及動畫層重疊情況的同時,還可以定義初始顯示位置,圖中 Z 列表示在圖層中 的位置(最前面為 0)。下圖中各項目的含義:編輯中的場景從下至上按 Base、Water、Things、Trees 平鋪層的順序依次重疊,上面的兩個動 畫層 Karel 和 Thomas 也在配置中。
圖 9 場景中的圖層編輯
■編寫角色動作及游戲推進等程序
步驟 5。
目前,游戲生成器的功能就是這些,它可以用來准備游戲中使用的背景、結構件和角色。這些信息都保存在類文件中,可以通過獲取方法訪 問它們。隨後,我們可以從 GameCanvas 類或其他類中訪問這些信息,從而實現游戲操作。所有這些都可通過直接編寫 Java 程序來實現。
在實際編寫游戲時,從必要的作業整體來看,MIDP 2.0 的游戲 API 能做到的只是編程作業的冰山一角,而游戲生成器可以做到的又是這其 中的一小部分。如果您對實際的游戲開發感興趣,建議多閱讀這方面的相關書籍。