怎樣在遊戲設計製作中實現指令碼控制(轉)

post0發表於2007-08-12
怎樣在遊戲設計製作中實現指令碼控制(轉)[@more@]

  一個遊戲引擎做好了,最重要的是缺什麼?指令碼。打個比方,遊戲引擎是一部電腦,則指令碼就是電腦的軟體。既然指令碼這麼重要,那該怎樣實現呢?下面我就來說說我的做法。

  首先理解一下訊息迴圈

  一個好的遊戲離不開好的訊息迴圈。它是遊戲實現很重要的一部分。下面我就來說說我的遊戲《宿命傳說》的做法。

  首先,我定義了一個全域性變數extern int GameState;

  在遊戲中定義了許多當前的遊戲狀態例如

  #define GAME_STATE_CUSTOM 0 //這代表在戰鬥中玩家可以控制遊戲

  #define GAME_STATE_TALKING 1

  等等。

  好了,下面在WinMain裡面的while(1)迴圈中有個UpdateScreen()函式

  原型為

  void UpdateScreen()

  {

  延時

  switch(GameState)

  {

  case GAME_STATE_CUSTOM:

  畫出地圖

  畫出所有精靈

  畫出天氣(如果有的話)

  如果玩家選中了敵人的話(打個比方DrawFlag=DrawEnemyState)就顯示敵人的移動範圍和敵人狀態

  break;

  case GAME_STATE_TALKING:

  GameDialogProc();

  break;

  case GAME_STATE_SCRIPTCONTROLLING:

  ScriptControlProc();

  break;

  ….//其他的訊息在這裡處理

  }

  將緩衝表面的圖象顯示到螢幕;

  }

  每個遊戲狀態都需要一個獨立的函式來寫。這樣在每次切換遊戲狀態時都不會出現無法處理的情況。

  在處理鍵盤訊息的時候我也用一個個獨立的函式來寫

  如處理Enter鍵我用了 KeyReturnProc()來控制

  在這個函式里同樣也少不了switch(GameState)這一句,為什麼?

  答案很簡單,比如說在精靈行走時Enter鍵就沒有用,這是我沒有處理精靈行走這個狀態的鍵盤訊息。而在戰鬥場景裡按下Enter鍵,如果有精靈在選擇框裡的話,就會處理相應的東西。

  例如選擇了敵人則使DrawFlag=DrawEnemyState;這樣在更新螢幕時就會畫出敵人的移動範圍和狀態。

  明白了嗎?好了,如果你明白了訊息迴圈的原理,下面的東西就很容易理解了。

  下面談談指令碼控制

  要實現這個,就必須在UpdataScreen()這個函式中攔截一個“指令碼控制”的訊息,並呼叫相應的處理函式:ScriptControlProc();

  那麼怎樣得到“指令碼控制”這個訊息呢?

  我是這樣約定的:新遊戲->呼叫指令碼

  "戰鬥結束"->呼叫指令碼

  “前往下一個地點”->呼叫指令碼

  好了,就只有這幾種情況下才呼叫,呼叫指令碼的函式為BeginScriptControl();

  這個函式做了三個工作:

  1.首先讀取舞臺(場景)角色的資料(沒一關都是一個不同的舞臺)

  2.開啟指令碼檔案(注意要用全域性的檔案指標)(雖然我在源程式中沒直接開啟,但是原理是一樣的)

  3.將遊戲狀態設定為“指令碼控制”以便在下一次UpdateScreen()中呼叫的是ScriptControlProc();(怎麼樣?知道訊息迴圈的作用了吧?)

  ScriptControlProc()這個函式其實也很簡單:

  讀取指令碼檔案中的引數直到檔案結束

  讀取指令碼檔案需要一個解釋指令碼的函式LoadParam(FILE*fp);

  這個函式負責解釋指令碼中的東西:是函式呼叫還是函式引數

  然後找到相應的函式執行即可

  比如說指令碼里有一段程式碼MovePlayerTo(1,1,1);

  意思就是把第1個玩家移動到1,1處

  怎樣做呢?

  我是按照以下幾步做的

  1.儲存當前的遊戲狀態

  2.把當前遊戲狀態設定為“移動精靈”

  當引擎得到“移動精靈”這個函式後,在UpdataScreen()中呼叫的是

  MoveRoleProc()這個函式

  當移動結束後,MoveRoleProc()呼叫EndMoveRole(),這個函式的作用就是

  讀取先前的遊戲狀態

  怎麼樣?又回到讀指令碼了吧?記住在移動角色的時候指令碼檔案的指標沒有改變,

  所以回到讀指令碼的這個函式後不是重新讀取而是繼續讀取!

  同理其他的指令碼指令如LoadDialog也是一樣的道理!

  當檔案要結束的時候,別忘了告訴引擎該停止了,這時候我們必須更新遊戲狀態

  指令碼里的SetGameState就是負責這項工作的。

  好了,先講到這裡,如果你有什麼不明白的地方請聯絡我

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/8225414/viewspace-951671/,如需轉載,請註明出處,否則將追究法律責任。

相關文章