遊戲畫面管理與切換控制

摘要

以 XNA 為基礎的遊戲程式雖然可以很容易地顯示圖形和文字供使用者檢視,並附予各種特殊效果,豐富遊戲的內容,以達到吸引遊戲使用者的最終目標。但是 XNA Framework 不像一般支援應用程式開發的 .NET Framework、.NET Compact Framework、或是 Silverlight Framework,對應用程式介面的開發提供完整的支援,XNA Framework 主要的支援在遊戲功能的設計,在支援應用程式介面方面,例如視窗、對話方塊、功能表、工具列、狀態列等和使用者溝通的介面部分就需要多投入一點心力,才能建置具功能選單、場景切換、或是允許使用者設定遊戲主角、遊戲內容、和遊戲難度的完整遊戲。在這一篇文章中,我們將要介紹以 XNA 為基礎的遊戲程式的畫面切換控制技巧,以及 XNA Framework 在與使用者溝通方面的支援。

 遊戲畫面管理與切換控制

和一般的應用程式一樣,以 XNA 為基礎的遊戲程式也需要功能選單供遊戲使用者選擇喜好設定,包括遊戲的背景圖案、主角人物的圖片、對戰的對象、或是遊戲的難度。每一種設定的設定畫面都可能有更進一步的細部設定,造成遊戲程式必須協助使用者無障礙地在各種設定畫面與遊戲進行畫面之間的切換,不會因為對遊戲的使用者造成操作上的困擾。

遊戲程式和一般的應用程式的定位不同,遊戲程式通常不需要使用者輸入很多的資料,甚至允許使用者不需要執行任何輸入的動作就可以進入遊戲程式設定的遊戲場景,所以在支援畫面設計與管理的功能方面較為薄弱,例如支援設計 Windows Phone 7 遊戲程式開發的 XNA Framework 不像支援設計一般的 Windows Phone 7 應用程式的 Silverlight Framework 可以很容易地利用 XAML 文件與 PhoneApplicationPage 類別建立和供使用者操作的畫面,和使用者進行溝通,或是讀取使用者設定或輸入的資料,並利用 NavigationService 類別提供的 Navigate、GoForward、和 GoBack 等方法進行切換,開發以 XNA 為基礎的遊戲程式必須投入較多的心力在管理遊戲程式的遊戲畫面、功能表畫面、或是設定畫面,以提供完整的遊戲程式功能供使用者使用。

 認識 Game State Management 範例

要為以 XNA 為基礎的遊戲程式加上功能表選單,設定畫面,或是場景切換功能,除了自行開發以外,也可以利用發表於 APP HUB 網站的 Game State Management 範例程式 (網址:http://create.msdn.com/en-US/education/catalog/sample/game_state_management),此範例程式提供三種遊戲平台的範例,分別是 Windows Phone 7 平台的範例:GSMSample_4_0_PHONE.zip;Windows 平台和 XBOX 遊戲機平台的範例:GSMSample_4_0_WIN_XBOX.zip,有興趣的讀者可以自行下載 Game State Management 範例程式提供的原始碼,為上述三種平台的遊戲程式加入遊戲畫面管理與切換的功能。如果讀者有需要開發網路遊戲程式,可以參考發表於 APP HUB 網站的 Network Game State Management 範例程式(網址:http://create.msdn.com/en-US/education/catalog/sample/network_game_state_management)。

[注意]

使用 Game State Management 範例程式提供的原始碼必須遵守 Microsoft Permissive License 授權規範,詳細的授權規定請參考 Microsoft Permissive License (Ms-PL) 文件的說明。

欲使用 Game State Management 範例程式提供的原始碼,請先下載正確的範例版本,解壓縮之後使用 Visual Studio 2010 Express 開啟副檔名為 .sln 的方案檔,您將可以在 [Solution Explorer] 視窗中看到名稱為 GameStateManagementSample (Phone) 的遊戲程式專案,以及名稱為 Content 的 Content Pipeline 專案。

名稱為 GameStateManagementSample (Phone) 的遊戲程式專案中名稱為 ScreenManager 的資料夾中有三個重要的原始程式檔案,分別是負責管理遊戲畫面的 ScreenManager.cs,可以協助處理使用者輸入的 InputState.cs,以及做為遊戲程式畫面基底類別的 GameScreen.cs。ScreenManager 資料夾底下的原始程式檔案的用途可以參考表1的說明:

表1:ScreenManager 資料夾底下的原始程式檔案的用途
原始程式檔案名稱 定義的類別名稱 用途
ScreenManager.cs ScreenManager 提供管理多個 GameScreen 類別的物件的功能,負責呼叫 GameScreen 類別的物件的 Update 方法更新畫面的狀態,呼叫 GameScreen 類別的物件的 Draw 方法更新畫面顯示的內容,以及將使用者的輸入的動作轉交給目前顯示的 GameScreen 類別的物件。
InputState.cs InputState 負責處理使用者透過鍵盤、遊戲控制器、和觸控面板的輸入操作。
GameScreen.cs GameScreen 代表一個遊戲畫面,包括遊戲的主功能表、設定功能表、和遊戲的主畫面,都是一個 GameScreen 類別的物件。

[說明]

ScreenManager 類別繼承自 XNA Framework 內建的 DrawableGameComponent 類別。XNA Framework 內建的 DrawableGameComponent 類別和 GameComponent 類別都是支援模組化遊戲設計的基底類別,兩者皆支援 Update 方法,以執行更新遊戲狀態的動作,DrawableGameComponent 另外支援 LoadContent、UnloadContent、以及 Draw 方法,做為載入遊戲資源、釋放資源、以及繪製遊戲內容之用。以 XNA 為基礎的遊戲程式可以將遊戲的人物和模組製作成繼承自 DrawableGameComponent 類別或 GameComponent 類別的衍生類別,將更新遊戲狀態、載入/釋放資源、與繪製遊戲內容的工作封裝在類別中,使遊戲程式具備更優良的結構。

[提示]

每一個繼承自 GameScreen 類別的衍生類別可以經由覆寫 (override) LoadContent 方法載入畫面需要用到的資源,覆寫 UnloadContent 方法執行釋放資源的動作,覆寫 Update 方法以執行更新畫面狀態的動作,覆寫 HandleInput 方法以處理使用者的輸入操作,覆寫 Draw 方法以顯示畫面的內容。除此之外,GameScreen 類別另外提供允許衍生類別覆寫的 Serialize 方法和 Deserialize 方法,執行儲存畫面狀態,或是讀回之前儲存的畫面狀態的動作。如果有需要控制畫面轉場的效果,可以設定 GameScreen 類別的 TransitionOnTime 屬性和 TransitionOffTime 屬性,將 TransitionOnTime 屬性和 TransitionOffTime 屬性設定成 0 代表畫面切換不需要轉場效果。如果畫面要以突現的方式蓋在目前的畫面之上,可以將 GameScreen 類別的 IsPopup 屬性設定成 true。

除了名稱為 ScreenManager 的資料夾以外,名稱為 GameStateManagementSample (Phone) 的遊戲程式專案中還有一個名稱為 Screens 的資料夾,位於此資料夾底下的是 Game State Management 範例程式提供的現成遊戲程式畫面,您可以直接使用 GameStateManagementSample (Phone) 的遊戲程式專案提供的遊戲畫面,或是自行開發繼承自 GameScreen.cs 定義的 GameScreen 類別的衍生類別,定義所開發的遊戲程式需要的畫面。

Screens 資料夾底下的原始程式檔案的用途可以參考表2 的說明:

表2:Screens 資料夾底下的原始程式檔案的用途
原始程式檔案名稱 定義的類別名稱 用途
BackgroundScreen.cs BackgroundScreen 做為遊戲背景的畫面。
GameplayScreen.cs GameplayScreen 遊戲的執行畫面。
LoadingScreen.cs LoadingScreen 顯示載入中,請使用者稍候的訊息的畫面。
MainMenuScreen.cs MainMenuScreen 主功能表選單畫面。
MenuEntry.cs MenuEntry 代表功能表中的功能選項的類別。
MenuScreen.cs MenuScreen 所有的功能表畫面的基底類別。
MessageBoxScreen.cs MessageBoxScreen 顯示訊息供使用者檢視的畫面。
OptionsMenuScreen.cs OptionsMenuScreen 提供設定畫面供使用者進行喜好設定的畫面。
PlayerIndexEventArgs.cs PlayerIndexEventArgs 功能表被使用者選中時引發的Selected事件伴隨的事件參數。

[提示]

請注意 ScreenManager 資料夾和 Screens 資料夾中的某些類別需要使用到 Content Pipeline 專案中的遊戲資源,也就是您必須在 Content Pipeline 專案中準備好必要的遊戲資源,否則光有類別的原始碼還是無法製作出遊戲程式需要使用的遊戲畫面。

需要使用到資源的原始程式碼檔案包括負責管理遊戲畫面的 ScreenManager.c 會用到 Content Pipeline 專案中名稱為 blank 的圖片和 menufont 字型定義檔;負責顯示訊息視窗和使用者溝通的 MessageBoxScreen.cs 會用到 Content Pipeline 專案中名稱為 gradient 的圖片;負責扮演遊戲主視窗的 GameplayScreen.cs 會用到 Content Pipeline 專案中名稱為 gamefont 字型定義檔,而當做背景視窗的 BackgroundScreen.cs 則需要用到 Content Pipeline 專案中名稱為 background 的圖片。請注意如果遊戲程式需要改變上述置於 Content Pipeline 專案的遊戲資源的名稱,必須一併修改使用到這些資源的原始程式碼,否則所開發的遊戲程式將無法執行。

 使用 Game State Management 範例提供的原始碼管理遊戲程式的畫面

了解 Game State Management 範例提供的原始程式檔案的功能和用途之後,我們就可以利用範例製作好的類別來開發具備功能表與畫面切換功能的遊戲程式了。

首先請啟動 Visual Studio 2010 Express for Windows Phone,建立一個 [Windows Phone Game(4.0)] 型態的專案,然後將 Game State Management 範例的遊戲程式專案中的 ScreenManager 資料夾和 Screens 資料夾中的所有檔案加入到所建立的遊戲程式專案中,將 Game State Management 範例的 Content Pipeline 專案中的 background.png、blank.png、gradient.png、gamefont.spritefont、和menufont.spritefont 加入到所建立的遊戲程式專案附屬的 Content Pipeline 專案中。

做好之後請編輯 Game1 類別,於原始程式檔案的最前面引入以下的名稱空間:

C#
using GameStateManagement;

然後於 Game1 類別中宣告以下的變數,負責管理遊戲程式需要使用的所有畫面:

C#
ScreenManager screenManager;				//管理遊戲畫面的 ScreenManager 類別的物件

再把 Game1 類別的建構函式編輯成以下的樣子,負責設定遊戲視窗的寬度和高度,建立負責管理遊戲畫面的 ScreenManager 類別的物件:

C#
public Game1()
{
graphics = new GraphicsDeviceManager(this);
    Content.RootDirectory = "Content";
graphics.PreferredBackBufferWidth = 480;				//設定遊戲視窗的寬度為 480
    graphics.PreferredBackBufferHeight = 800;				//設定遊戲視窗的高度為 800
    screenManager = new ScreenManager(this);			  //建立 ScreenManager 類別的物件
Components.Add(screenManager);		//將 ScreenManager 類別的物件加入到 Components 集合
if (!screenManager.DeserializeState())	       //如果沒有前一次執行儲存的畫面狀態
    {
        screenManager.AddScreen(new BackgroundScreen(), 
null);				//建立遊戲背景畫面,並交給 ScreenManager 管理
        screenManager.AddScreen(new MainMenuScreen(), 
null);				//建立主功能表畫面,並交給 ScreenManager 管理
    }
    TargetElapsedTime = TimeSpan.FromTicks(333333);
}

請注意,遊戲程式執行時需要用到的所有畫面都必須交給 ScreenManager 管理。

[提示]

因為 ScreenManager 類別繼承自 DrawableGameComponent 類別,當 DrawableGameComponent 類別的衍生類別的物件加入到 Game1 類別的 Components 集合之後,每次 Game1 類別的 LoadContent 方法、Update 方法、和 Draw 方法被呼叫的時候,DrawableGameComponent 類別的衍生類別的物件的 LoadContent 方法、Update 方法、和 Draw 方法也會被呼叫,讓 DrawableGameComponent 類別的衍生類別的物件能夠載入遊戲資源,更新狀態,並繪製物件的內容。

編輯妥 Game1 類別的建構函式之後,請覆寫 OnExiting 方法,在遊戲程式結束執行時將畫面的狀態儲存下來,以便下一次執行遊戲程式的時候還原到上一次結束執行時的畫面。請為 Game1 類別加入以下的 OnExiting 方法:

C#
protected override void OnExiting(object sender, EventArgs args)
{
    screenManager.SerializeState();	//呼叫 screenManager 的 SerializeState 方法儲存遊戲畫面
    base.OnExiting(sender, args);
}

最後我們必須編輯 Game1 類別的 Update 方法中,將判斷使用者是否按下 Windows Phone 7 智慧型手機左下方的 Back 硬體按鍵的程式碼註解掉,因為加入畫面控制功能的遊戲程式在使用者按下智慧型手機左下方的 Back 硬體按鍵時,如果有上一個遊戲畫面,則必須回到上一個遊戲畫面,而不是結束遊戲程式的執行,編輯妥的 Update 方法如下:

C#
protected override void Update(GameTime gameTime)
{
    //if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
    //    this.Exit();
    base.Update(gameTime);
}

做好之後請執行遊戲程式專案,您將會看到遊戲程式提供的主功能表,如圖1 所示:

圖1:遊戲程式提供的主功能表

按下畫面中的 [Options] 功能,您就會看到遊戲程式的設定畫面,點選設定畫面中的功能表,可以看到模擬設定值改變的效果,如圖2 所示:

圖2:遊戲程式的設定畫面

按下 Windows Phone 7 智慧型手機左下方的 Back 硬體按鍵回到圖1的畫面,再點選 [Play Game] 功能,您就會看到一個簡單的遊戲執行的情形,如圖3 所示:

圖3:簡單的遊戲執行的情形

按下 Windows Phone 7 智慧型手機左下方的 Back 硬體按鍵可以回到主功能表,再按一次可以結束遊戲程式的執行。

[Game State Management 範例使用要訣]

因為 Game State Management 範例提供的原始程式檔案中,當做所有遊戲畫面基底類別的 GameScreen 類別內容儲存/讀回遊戲畫面狀態的功能,所以在遊戲畫面管理和切換的功能尚未製作完善之前,先將製作好的遊戲程式部署至 Windows Phone 7 Emulator (模擬器) 執行,如果功能不正確,則將模擬器關閉,丟棄儲存的遊戲畫面狀態,待程式修改妥後,再將修改後的程式重新部署到模擬器執行。

您可以視需要修改 MainMenuScreen.cs 的程式碼,提供不同的功能表供使用者操作,不要忘了請一併編輯 Content Pipeline 專案中的 menufont.spritefont 字型定義檔,定義功能表需要顯示的文字。如果需要為所開發的遊戲程式提供中文功能表,請參考 [圖形特效與文字顯示] 一文的說明,於 Content Pipeline 專案中的 menufont.spritefont 字型定義檔定義好欲顯示的中文字和字型規格。

欲修改遊戲程式的主功能表,請編輯 MainMenuScreen.cs 原始檔案的 MainMenuScreen 類別的建構函式中建立 MenuEntry 類別的物件的語法,如下:

C#
public MainMenuScreen() : base("Main Menu")
{
    MenuEntry playGameMenuEntry = new MenuEntry("Play Game");
    MenuEntry optionsMenuEntry = new MenuEntry("Options");
    playGameMenuEntry.Selected += PlayGameMenuEntrySelected;
    optionsMenuEntry.Selected += OptionsMenuEntrySelected;
    MenuEntries.Add(playGameMenuEntry);
    MenuEntries.Add(optionsMenuEntry);
}

當然,修改建立 MenuEntry 類別的物件的語法必須一併修改 MenuEntry 類別的 Selected 事件的事件處理程序,如下:

C#
void PlayGameMenuEntrySelected(object sender, PlayerIndexEventArgs e)
{
     LoadingScreen.Load(ScreenManager, true, e.PlayerIndex, new GameplayScreen());
}
void OptionsMenuEntrySelected(object sender, PlayerIndexEventArgs e)
{
    ScreenManager.AddScreen(new OptionsMenuScreen(), e.PlayerIndex);
}

請注意 [Options] 功能表的 Selected 事件的事件處理程序會直接顯示 OptionsMenuScreen 類別定義的內容,而 [Play Game] 功能表的 Selected 事件的事件處理程序則會先顯示 LoadingScreen 類別定義的內容,讓使用者先看到 [Loading…] 的文字,然後才看到 GameplayScreen 類別定義的內容。

以 GameplayScreen 類別為例,其建構函式就有設定 TransitionOnTime 屬性和 TransitionOffTime 屬性,表示切換到 GameplayScreen 畫面和切換離開 GameplayScreen 畫面都要顯示轉場效果。GameplayScreen 類別的建構函式如下:

C#
public GameplayScreen()
{
    TransitionOnTime = TimeSpan.FromSeconds(1.5);
    TransitionOffTime = TimeSpan.FromSeconds(0.5);
}

最後我們只要將遊戲的功能製作在扮演遊戲主畫面的 GameplayScreen.cs 檔案中,或置換掉 GameplayScreen.cs 檔案的內容,就可以完成提供主功能表和遊戲設定畫面的遊戲程式了。

 利用 Guide 類別與遊戲使用者溝通

以 XNA 為基礎的遊戲程式除了可以利用主功能表和設定畫面與使用者溝通之外,也可以利用 Guide 類別提供的功能和使用者溝通,包括顯示訊息畫面供使用者檢視和顯示輸入畫面協助使用者輸入資料等常用的使用者介面。

欲利用 Guide 類別提供協助使用者輸入資料的操作畫面並顯示訊息畫面,請先於原始程式檔案的最前面引入以下的名稱空間:

C#
using Microsoft.Xna.Framework.GamerServices;
using System;
using System.Collections.Generic;

然後於類別中宣告以下的變數

C#
string typedText;								//存放使用者輸入的資料的變數

需要顯示協助使用者輸入資料的操作畫面的時候,只要透過下列的程式碼,就可以利用 Guide 類別的 BeginShowKeyboardInput 方法顯示供使用者輸入資料的畫面:

C#
Guide.BeginShowKeyboardInput(PlayerIndex.One,
                        "Here's your Keyboard", "Type something...",
                        ((typedText == null) ? "" : typedText),
                        GetTypedChars, null);			//顯示供使用者輸入資料的畫面

當使用者完成輸入並按下輸入畫面中的 [OK] 鍵時,就會執行到名稱為 GetTypedChars 的方法,由 GetTypedChars 方法呼叫 Guide 類別的 EndShowKeyboardInput 方法取得使用者輸入的內容,做法如下:

 

C#
protected void GetTypedChars(IAsyncResult r)
{
    typedText = Guide.EndShowKeyboardInput(r);			//取得使用者輸入的內容
}

做好之後請執行遊戲程式,執行顯示協助使用者輸入資料的功能,您就會看到如圖4 所示的畫面:

圖4:協助使用者輸入資料的畫面

如果遊戲程式需要顯示訊息和使用者溝通,要求使用者做決策,就可以利用 Guide 類別的 BeginShowMessageBox 方法顯示訊息畫面供使用者做決策。例如以下就是 Guide 類別的 BeginShowMessageBox 方法的使用技巧:

C#
string msg = "Quit Game?";            					//準備供使用者檢視的訊息
List<string> MBButtons = new List<string>();			//準備供使用者選擇的按鍵的集合
MBButtons.Add("Yes");								//加入 Yes 鍵到MBButtons集合
MBButtons.Add("No");									//加入 No 鍵到MBButtons集合
Guide.BeginShowMessageBox("Game Over", msg, MBButtons, 0,
                    MessageBoxIcon.Alert, GetMBResult, null);//顯示訊息畫面和使用者溝通

當使用者按下訊息畫面中的按鍵時會呼叫到名稱為 GetMBResult 的方法,由 GetMBResult 方法判斷使用者的按鍵選擇。以下的 GetMBResult 方法會呼叫 Guide 類別的 EndShowMessageBox 方法取得使用者的按鍵狀態:

C#
protected void GetMBResult(IAsyncResult r)
{
    int? b = Guide.EndShowMessageBox(r);					//取得使用者的按鍵狀態
    if (b == 0)										//使用者按下第一個按鍵
    {
        //user click Yes
    }
    else											//使用者按下第二個按鍵
    {
        //user click No
    }
}

請注意呼叫 Guide 類別的 EndShowMessageBox 方法取得的結果是一個整數,其內容值為 0 代表使用者按下第一個按鍵,其內容值為 1 代表使用者按下第二個按鍵,其內容值為 2 代表使用者按下第三個按鍵,以此類推。

做好之後請啟動遊戲程式,執行顯示訊息和使用者溝通的功能,您就會看到圖5 的畫面:

圖5:利用 Guide 類別顯示訊息和使用者溝通的畫面

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值