第十章 遊戲迴圈的設計
前面的幾章中,曾多次提到遊戲迴圈,這一章就讓我們一起瞭解遊戲迴圈的相關概念,學習如何使用遊戲迴圈。
我們知道,遊戲的主體通常在一個迴圈體中,最初,我們用一個變數來表示遊戲的狀態,比如
gameState = STATE_STARTMENU;
每次迴圈都判斷目前狀態,調用不同的函數進行處理。這種方法簡單有效,所有的邏輯代碼都在一個類裡,不必考慮隱藏和劃分,只需要定義一些函數即可。但是它的優點也是它的缺點,這種結構化的方法通常讓程式顯得很大,有些混亂。所以我們採用另一種方式管理遊戲迴圈,將情境(Scene)的概念引入程式中。
我們可以認為一個遊戲由一些獨立的情境組成,如開始菜單,遊戲中畫面,過關畫面等等都可以是情境,而整個遊戲就在這些情境之間不斷切換,直到退出為止。情境這個詞用在這裡非常貼切,所有遊戲的元素,不論是選項菜單還是玩家角色,都像是舞台上的演員(Actor),他們根據不同的情境登上舞台或離開舞台。有了情境的支援,演員們不再擠在一起,而是被劃分成一組一組的,彼此隔離,這樣會讓程式變得清晰有序,而遊戲迴圈就變成了情境迴圈。
我們首先建立一個SceneBase類,作為所有Scene的基類:
public abstract class SceneBase {
abstract public void tick();
abstract public void update(Canvas c);
}
其中tick為一個動畫幀,讓所有演員做出動作。update將演員們顯示在舞台上。
然後,我們在GameView建立一個SceneBase類型的變數來表示當前的情境,只有當前的情境才會被繪製。
static SceneBase currentScene;
……
if(c != null) {
currentScene.tick();
currentScene.update(c);
}
最後通過一個函數改變當前情境,這就實現了最基本情境轉換。
public static void setCurrentScene(SceneBase scene) {
currentScene = scene;
}
為了測試這種方案,我們建立兩個情境類SceneStartMenu和SceneMain分別表示開始菜單和遊戲主迴圈,通過點擊螢幕在這兩個情境之間切換。
我們首先在GameView中定義這兩個情境
static SceneStartMenu sceneStartMenu = null;
static SceneMain sceneMain = null;
在GameView的建構函式中初始化sceneStartMenu,將它作為初始情境
if(sceneStartMenu == null)
sceneStartMenu = new SceneStartMenu();
setCurrentScene(sceneStartMenu);
然後我們在GameView中重載onTouchEvent(也要為SceneBase增加一個響應的函數)
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
return currentScene.onTouchEvent(event);
}
在SceneStartMenu中
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
if(GameView.sceneMain == null)
GameView.sceneMain = new SceneMain();
GameView.setCurrentScene(GameView.sceneMain);
break;
}
return true;
}
SceneMain與之相反即可
然後我們修改兩個scene的update函數
public void update(Canvas c) {
// TODO Auto-generated method stub
c.drawARGB(255, 0, 0, 0);
c.drawText("SceneStartMenu", GameView.width/2, GameView.height/2, paint);
}
這樣就能知道當前的Scene是哪一個了
現在讓我們運行一下這個程式,點擊螢幕,可以看到兩個情境之間切換的效果。到此為止,本章的內容就講完了,很短是吧,但是很有用,有了這個結構,加上前一章的生命週期控制,你的程式會變得更整潔有序。當然,在具體應用中,你必須擴充scene的內容,比如情境之間的互動,你可能需要一個或幾個setter或者Map結構(模仿Activity)。請保持情境之間傳遞的是數值而不是執行個體,是設定給演員的指令而不是演員本身。
本章樣本程式http://u.115.com/file/f1cf493609