02 XNA Framework 常用的類別

摘要

上一回我們爲大家介紹瞭如何使用 Visual Studio 2010 或 Visual Studio 2010 Express for Windows Phone 設計以 XNA 爲基礎的 Windows Phone 7 遊戲程序,並瞭解以 XNA 爲基礎的遊戲程序的基礎架構與核心功能。這一回我們將要爲大家介紹 XNA Framework 支持遊戲程序製作的重要類別,做爲開發遊戲程序的基礎知識。除此之外,我們也將利用本文所介紹的類別實作一個簡單的遊戲程序,並令其具有能夠不斷捲動的背景圖案。

GraphicsDeviceManager 類別

第一個要介紹給大家認識的是負責管理繪圖裝置的 GraphicsDeviceManager 類別。以 XNA 爲基礎的遊戲程序必須在初始化的時候建立妥 GraphicsDeviceManager 類別的對象,並設定包括遊戲程序窗口高度與寬度在內的必要屬性,做爲顯示遊戲內容的基礎。有關於遊戲程序初始化階段建立 GraphicsDeviceManager 類別的對象的詳細做法可以參考 [設計以 XNA 爲基礎的 Windows Phone 7 遊戲]一文的說明。表1 所示即爲 GraphicsDeviceManager 類別常用的屬性:

表1:GraphicsDeviceManager 類別常用的屬性
屬性名稱 說明
IsFullScreen 控制遊戲程序的窗口是否要以全屏幕的方式顯示
PreferredBackBufferFormat 屏幕緩衝區的格式
PreferredBackBufferHeight 屏幕緩衝區的高度
PreferredBackBufferWidth 屏幕緩衝區的寬度

 

GraphicsDeviceManager 類別常用的方法請參考表2 的說明:

表2:GraphicsDeviceManager 類別常用的方法
方法名稱 說明
ToggleFullScreen 在窗口模式和全屏幕模式中切換

遊戲核心類別

以 XNA 爲基礎的遊戲程序的主體是 Game 類別,也是做爲遊戲程序主體的 Game1 類別的基礎類別。遊戲程序可以利用 Game1 類別的 Update 方法更新遊戲的狀態,利用 Draw 方法顯示遊戲的內容。表3 所示即爲 Game 類別的常用屬性:

表3:Game 類別常用的屬性
屬性名稱 說明
Components 管理所有 GameComponent 的集合
Content 取得 ContentManager 對象的屬性
GraphicsDevice 取得圖型裝置對象的屬性
IsActive 判斷遊戲程序的窗口目前是否在作用中
IsFixedTimeStep 控制遊戲程序要使用固定更新模式或是可變更新模式
TargetElapsedTime 當 IsFixedTimeStep 屬性的內容值爲 true 時,控制 Update 方法被呼叫的頻率的屬性

 

Game 類別常用的方法可以參考表4 的說明:

表4:Game 類別常用的方法
方法名稱 說明
Exit 結束遊戲程序的執行
BeginDraw 宣告繪製圖形的動作開始
EndDraw 宣告繪製圖形的動作結束
Draw 執行繪製遊戲內容的動作
LoadContent 執行加載遊戲資源的方法
UnloadContent 執行釋放遊戲資源的方法
Update 負責更新遊戲狀態的方法

 

如果程序設計師要以模塊化的方式設計遊戲程序,可以將遊戲的人物製作成 GameComponent 類別或是 DrawableGameComponent 類別,再將 GameComponent 類別的對象或是 DrawableGameComponent 類別的對象加入到 Game 類別的對象的 Conponents 集合中,由 Game 類別的對象統一管理,把複雜的遊戲人物的初始化、狀態更新、以及更新顯示等動作封裝在 GameComponent 類別或是 DrawableGameComponent 類別中,可以有效簡化 Game 類別的控制邏輯。當遊戲人物衆多,角色複雜時,適當地利用 GameComponent 類別或是 DrawableGameComponent 類別可以提升遊戲的可維護性,利於發展功能進階,效果複雜的遊戲。

XNA Framework 提供的 GameComponent 類別和 DrawableGameComponent 類別的差別在於 DrawableGameComponent 類別管理的是有用戶接口的遊戲組件,而 GameComponent 類別所管理的則是沒有用戶接口的遊戲組件。換句話說,DrawableGameComponent 類別提供了 GameComponent 類別未支持的 LoadContent 方法和 Draw 方法,以便執行加載所管理的遊戲資源和顯示遊戲的內容的工作。

當建立好 GameComponent 類別的對象或 DrawableGameComponent 類別的對象之後,只要將 GameComponent 類別的對象或 DrawableGameComponent 類別的對象加入到 Game 類別的對象的 Components 集合中,GameComponent 類別的對象或 DrawableGameComponent 類別的對象的 Update 方法就會被持續地呼叫,而 DrawableGameComponent 類別的對象的 Draw 方法也會在適當的時機被呼叫,並將遊戲的內容顯示到窗口中供用戶操作。

欲爲遊戲程序項目加入 GameComponent 類別或 DrawableGameComponent 類別,可以使用鼠標的右鍵點中 [Solution Explorer] 窗口中的項目名稱,從出現的菜單選擇 [Add | New Item] 功能,屏幕上就會出現要求選擇欲加入到項目的項目的窗口,如圖1 所示:

圖1:要求選擇欲加入到項目的項目的窗口

請於中間的窗口選擇 [Game Component] 項目,於 [Name] 字段輸入文件名,然後按下 [Add] 鍵,就可以爲項目加入一個繼承自 GameComponent 類別的衍生類別。

[注意]

繼承自 GameComponent 類別的衍生類別無法覆寫基礎類別的 LoadContent 方法和 Draw 方法,適合用來製作沒有用戶接口的遊戲組件。如果需要製作提供用戶接口的遊戲組件,可以在爲項目加入繼承自 GameComponent 類別的衍生類別之後,自行將所繼承的 GameComponent 基礎類別修改成 DrawableGameComponent 類別,就可以覆寫基礎類別的 LoadContent 方法和 Draw 方法,分別負責執行加載所管理的遊戲資源,和繪製遊戲內容的工作。

以下就是在繼承自 DrawableGameComponent 類別的衍生類別覆寫基礎類別的 LoadContent 方法和 Draw 方法的範例:

public class GameComponent1 : Microsoft.Xna.Framework.DrawableGameComponent
{
    …
    protected override void LoadContent()					//覆寫 LoadContent 方法
    {
        base.LoadContent();
    }
    public override void Draw(GameTime gameTime)					//覆寫 Draw 方法
    {
        base.Draw(gameTime);
    }
}
 

GameComponent 類別常用的屬性可以參考表5 的說明:

表5:GameComponent 類別常用的屬性
屬性名稱 說明
Enabled 控制 GameComponent 類別的對象是否啓用的屬性。當對象啓用時,類別的 Update 方法就會被定時地呼叫
UpdateOrder 控制 Update 方法被呼叫的順序。內容值小的對象的 Update 方法會優先被呼叫

 

GameComponent 類別常用的方法詳見表6 的說明:

表6:GameComponent 類別常用的方法
方法名稱 說明
Initialize 負責執行 GameComponent 類別的對象初始化的方法
Update 負責更新 GameComponent 類別的對象的狀態的方法

 

DrawableGameComponent 類別的功能和 GameComponent 類別的功能類似,差別在於 DrawableGameComponent 類別可以用來管理具用戶接口的遊戲組件。DrawableGameComponent 類別常用的屬性請參考表7 的說明:

表7:DrawableGameComponent 類別常用的屬性
屬性名稱 說明
Enabled 控制 DrawableGameComponent 類別的對象是否啓用的屬性。當對象啓用時,類別的 Update 方法就會被定時地呼叫
Visible 控制 DrawableGameComponent 類別的對象是否隱藏的屬性,對象隱藏時,類別的 Draw 方法將不會被呼叫
UpdateOrder 控制 Update 方法被呼叫的順序。內容值小的對象的 Update 方法會優先被呼叫
DrawOrder 控制 Draw 方法被呼叫的順序。內容值小的對象的 Draw 方法會優先被呼叫
Game 取得管理 DrawableGameComponent 類別的對象的Game類別對象的屬性
GraphicsDevice 取得遊戲程序使用的繪圖裝置的屬性

 

DrawableGameComponent 類別常用的方法請參考表8 的說明:

表8:DrawableGameComponent 類別常用的方法
方法名稱 說明
Initialize 負責執行 GameComponent 類別的對象初始化的方法
LoadContent 負責加載欲使用的遊戲資源
UnloadContent 負責釋放欲使用的遊戲資源
Update 負責更新遊戲的狀態
Draw 負責顯示遊戲的內容

 

製作好 GameComponent 類別或是 DrawableGameComponent 類別之後,我們就可以在 Game1 類別的建構函式中建立 GameComponent 類別或是 DrawableGameComponent 類別的對象,再將建立好的對象加入到 Game1 類別的對象的 Components 集合中,遊戲程序便會定時地呼叫 GameComponent 類別或是 DrawableGameComponent 類別的Update方法,以及 DrawableGameComponent 類別的 Draw 方法,達到更新遊戲狀態和顯示遊戲內容的效果。假設遊戲項目中已經製作好繼承自 GameComponent 類別的衍生類別,名稱爲 GameComponent1,以及繼承自 DrawableGameComponent 類別的衍生類別,名稱爲 DrawableGameComponent1,則 Game1 類別的建構函式就可以寫成以下的樣子:

public Game1()
{
    graphics = new GraphicsDeviceManager(this);
    Content.RootDirectory = "Content";
    graphics.PreferredBackBufferHeight = 480;
    graphics.PreferredBackBufferWidth = 800;
    Components.Add(new GameComponent1(this));
    Components.Add(new DrawableGameComponent1 (this));
    // Frame rate is 30 fps by default for Windows Phone.
    TargetElapsedTime = TimeSpan.FromTicks(333333);
 }
 

[提示]

XNA Framework 支持的 DrawableGameComponent 類別雖然可以用來管理遊戲程序的人物,但是卻沒有記錄遊戲人物座標位置的屬性,程序設計師可以自行於繼承自 DrawableGameComponent 類別的衍生類別加入負責記載遊戲人物座標的屬性,以形成一個完整的遊戲組件,利於遊戲程序進行定位與移動。

顯示 2D 與 3D 圖形

以 XNA 爲基礎的遊戲程序可以利用 Texture2D 類別管理 2D 圖形資源,利用 Model 類別管理 3D 模型。用來管理 2D 圖形資源的 Texture2D 類別常用的屬性可以參考表9 的說明,用來管理 3D 模型的 Model 類別的常用屬性可以參考表10 的說明:

表9:Texture2D 類別常用的屬性
屬性名稱 說明
Bounds 代表圖形資源的大小
Format 代表圖形資源的格式
GraphicsDevice 取得遊戲程序使用的繪圖裝置的屬性
Height 圖形資源的高度(單位:pixel)
Width 圖形資源的寬度(單位:pixel)

 

表10:Model 類別的常用屬性
屬性名稱 說明
Bones 3D 模型中的骨骼數據的集合
Meshes 3D 模型中的網格數據的集合
Root 取得最根源的骨骼數據的屬性

 

座標

當以 XNA 爲基礎的遊戲程序欲將所加載的 2D 或 3D 圖形資源顯示到遊戲的畫面時,我們就會需要用到和座標有關的型態。XNA 支持的常用座標類別包括定義 2 維空間座標點的 Vector2 結構,定義 3 維空間座標點的 Vector3 結構,以及定義齊次座標系統 (Homogenous Coordinate System) 座標點的 Vector4 結構。

Vector2 架構的是二維空間的座標,座標原點默認在窗口的左上角,如圖2 所示:

圖2:二維空間的座標系統

Vector2 結構的數據成員請參考表11 的說明:

表11:Vector2 結構的數據成員
數據成員名稱 說明
X 代表座標點的X軸的位置
Y 代表座標點的Y軸的位置

 

Vector2 結構常用的方法請參考表12 的說明:

表12:Vector2 結構常用的方法
方法名稱 說明
Add 對座標點執行加法運算
Clamp 限制座標內容值必須落在指定的範圍之間
Distance 計算兩個座標點之間的距離
DistanceSquared 計算兩個座標點之間的距離的平方
Divide 對座標點執行除法運算
Equals 判斷座標點是否等於指定的座標點
Lerp 計算兩個座標點之間的線性內插
Max 計算座標點的最大值
Min 計算座標點的最小值
Multiply 對座標點執行乘法運算
Negate 對座標點執行反運算
Subtract 對座標點執行減法運算
Transform 對座標點執行轉置 (Transform) 運算

 

Vector3 架構的是三維空間的座標,因爲 XNA Framework 支持右手座標系統 (Right-Handed System),其 Z 軸往使用者的方向遞增,如圖3 所示:

圖3:XNA 支持的右手座標系統

Vector3 結構的數據成員可以參考表13 的說明:

表13:Vector3 結構的數據成員
數據成員名稱 說明
X 代表座標點的X軸的位置
Y 代表座標點的Y軸的位置
Z 代表座標點的Z軸的位置

 

Vector3 結構常用的方法和 Vector2 結構常用的方法類似,但是有提供能夠計算外積 (Cross Product) 的 Cross 方法。

Vector4 架構的是齊次座標系統 (Homogeneous Coordinate System) 的座標點,第四個座標並非用來代表幾何空間的位置,而是用來表示座標軸的遠近參數。

Vector4 結構的數據成員可以參考表14 的說明:

表14:Vector4 結構的數據成員
數據成員名稱 說明
X 代表座標點的 X 軸的位置
Y 代表座標點的 Y 軸的位置
Z 代表座標點的 Z 軸的位置
W W 元素。W 元素並不是用來代表幾何空間的位置,而是爲了定義轉置矩陣的設計,利於執行平行、放大、與旋轉的處理

 

Vector4 結構常用的方法和 Vector2 結構常用的方法類似,可以直接參考表12 的說明。

捲動遊戲程序背景的做法

瞭解了 XNA Framework 支持遊戲設計的常用類別之後,接下來我們就要使用這些類別爲遊戲程序製作一個可以自動捲動的背景,就像超級瑪璃的遊戲一樣,在遊戲進行時不斷地捲動。

要製作遊戲的捲動背景,可以準備一張以上,組合起來會變成完整的背景圖的背景拼圖,例如以下就是由三張連續的背景拼圖組成的背景圖。

圖4:由三張連續的圖片拼湊而成背景圖

[說明]

遊戲的背景通常是由多張圖片拼湊而成,一張接着一張不斷地輪播,周而復始。請注意除非背景圖的內容永遠不會重複,否則不要使用單一張完整的背景圖片當做遊戲的背景,就算要製作背景圖內容永遠不重複的遊戲,也會因爲單一張完整的圖片體積過積而不切實際。

準備好當做遊戲背景的背景拼圖之後,請啓動 Visual Studio 2010 Express for Windows Phone,建立一個 [Windows Phone Game(4.0)] 型態的項目,並把準備好的背景拼圖加入到 [Solution Explorer] 窗口中的 Content Pipeline 項目中,以便被遊戲程序加載使用。

建立好項目之後請開啓 Game1.cs 原始程序檔案進行編輯,於 Game1 類別中加入以下的變量宣告,分別用來管理當做遊戲背景的拼圖,以及記載背景拼圖位置的變量:

Texture2D Background1;								//管理第一張背景圖片的變數
Texture2D Background2;								//管理第二張背景圖片的變數
Texture2D Background3;								//管理第三張背景圖片的變數

Vector2 Position1;									//第一張背景圖片的顯示座標
Vector2 Position2;									//第二張背景圖片的顯示座標
Vector2 Position3;									//第三張背景圖片的顯示座標
 

請注意上述的變量宣告可以處理由三張圖片拼湊而成的遊戲背景,如果遊戲背景是由更多圖片組成,可以宣告適量的變量以管理組成背景的圖片。

宣告好必要的變量之後,請修改 Game1 類別的建構函式,加入設定遊戲窗口大小的程序代碼,修改好的建構函式如下:

public Game1()
{
    graphics = new GraphicsDeviceManager(this);
    Content.RootDirectory = "Content";
    graphics.PreferredBackBufferWidth = 480;				//設定遊戲視窗的寬度為 480
    graphics.PreferredBackBufferHeight = 800;				//設定遊戲視窗的寬度為 400
    // Frame rate is 30 fps by default for Windows Phone.
    TargetElapsedTime = TimeSpan.FromTicks(333333);
}
 

設定好遊戲窗口的大小之後,請編輯 Game1 類別的 LoadContent 方法,負責加載當做背景圖片的圖形,並設定妥背景圖片的顯示位置,編輯好的 LoadContent 方法如下:

protected override void LoadContent()
{
    // Create a new SpriteBatch, which can be used to draw textures.
    spriteBatch = new SpriteBatch(GraphicsDevice);
    // TODO: use this.Content to load your game content here
    Background1 = Content.Load<Texture2D>("Background01");		//載入第一張背景圖片
    Position1 = new Vector2(0, 0);					//設定第一張背景圖片的顯示位置
    Background2 = Content.Load<Texture2D>("Background02");		//載入第二張背景圖片
    Position2 = new Vector2(Position1.X + 
Background1.Width, 0);	//設定第二張背景圖片要顯示在第一張背景圖片的右方
    Background3 = Content.Load<Texture2D>("Background03");		//載入第三張背景圖片
    Position3 = new Vector2(Position2.X + 
Background2.Width, 0); 	//設定第三張背景圖片要顯示在第二張背景圖片的右方
}
 

如果讀者準備的背景圖片的文件名和上述的範例程序代碼所指定的文件名不同,請依據所準備的圖形文件名修改上述指定加載的文件名。

完成加載遊戲程序的背景圖案之後,接下來我們必須修改 Game1 類別的 Update 方法,更新背景圖片顯示的位置,創造出背景捲動的效果。

如果要將遊戲的背景由右往左捲動,則每一次 Update 方法被呼叫的時候必須遞減所顯示的背景圖片的左上角點的 X 座標的內容值,令背景圖片產生往左移動的效果。反之,如果要將遊戲的背景由左往右捲動,則每一次 Update 方法被呼叫的時候必須遞增所顯示的背景圖片的左上角點的X座標的內容值,就能夠令背景圖片產生往右移動的效果。請注意如果背景圖是由右往左捲動,當最左邊背景圖捲動到遊戲的窗口之外時,必須自動補到最右邊的圖的右邊,背景圖才能夠周而復始地不斷地捲動,反之亦然。圖5 所示即爲最左邊的背景圖捲動到遊戲窗口的範圍之外時,自動接續到最右方的背景圖的右邊繼續顯示的示意圖:

圖5:捲動背景圖的做法

瞭解捲動背景圖的做法之後,請將 Game1 類別的 Update 方法修改成以下的樣,以由右往左的方式捲動背景圖:

protected override void Update(GameTime gameTime)
{
    // Allows the game to exit
    if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
        this.Exit();
    // TODO: Add your update logic here
    if (Position1.X < -Background1.Width)		//如果第一張背景圖離開遊戲的視窗
    {
        Position1.X = Position3.X + 
Background3.Width;				//令其顯示在第三張背景圖的右方的位置
    }
    if (Position2.X < -Background2.Width)		//如果第二張背景圖離開遊戲的視窗
    {
        Position2.X = Position1.X + 
Background1.Width;				//令其顯示在第一張背景圖的右方的位置
    }
    if (Position3.X < -Background3.Width)		//如果第三張背景圖離開遊戲的視窗
    {
        Position3.X = Position2.X + 
Background2.Width;				//令其顯示在第二張背景圖的右方的位置
    }
    int aSpeed = 2;									//設定每次捲動的單位距離
    Position1.X -= aSpeed;					//令第一張背景圖往左移動指定的距離
Position2.X -= aSpeed;					//令第二張背景圖往左移動指定的距離
    Position3.X -= aSpeed;					//令第三張背景圖往左移動指定的距離
base.Update(gameTime);
}
 

[提示]

讀者只要稍加修改上述的 Update 方法,就可以令背景圖由左往右移動。如果要升高或降低背景的捲動速度,可以修改 aSpeed 變量的內容值。

最後我們只要將移動過的背景圖顯示到遊戲的窗口,就可以令遊戲程序的背景產生捲動的效果。請修改 Game1 類別的 Draw 方法,將每一張背景圖顯示在指定的位置,修改妥的 Draw 方法如下:

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.CornflowerBlue);
    // TODO: Add your drawing code here
    spriteBatch.Begin();
    spriteBatch.Draw(Background1, Position1, 
Color.White);		//在 Position1 的位置顯示第一張背景圖
    spriteBatch.Draw(Background2, Position2, 
Color.White);		//在 Position2 的位置顯示第二張背景圖
    spriteBatch.Draw(Background3, Position3, 
Color.White);		//在 Position3 的位置顯示第三張背景圖
    spriteBatch.End();
    base.Draw(gameTime);
}
 

做好之後請按下 CTRL+F5 組合鍵執行項目,所製作好的遊戲便會部署到 Windows Phone 7 的仿真器中執行,您將可以看到背景圖由右往左捲動的情形,其執行的畫面如圖6 所示:

圖6:背景圖由右往左捲動的遊戲程序執行的情形

範例下載:ScrollBackgound.zip

[結語]

這一次的文章中我們爲大家介紹了 XNA Framework 支持遊戲程序製作的重要類別,做爲開發遊戲程序的基礎知識。除此之外,我們也利用本文所介紹的類別實作一個簡單的遊戲程序,並令其具有能夠不斷捲動的背景圖案。下一回我們將會介紹更多的類別,讓讀者可以爲所製作的遊戲程序加入更豐富的遊戲效果。

發佈了24 篇原創文章 · 獲贊 7 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章