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 方法的範例:

XML
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 類別的建構函式就可以寫成以下的樣子:

XML
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 類別中加入以下的變數宣告,分別用來管理當做遊戲背景的拼圖,以及記載背景拼圖位置的變數:

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

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

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

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

XML
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 方法如下:

XML
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 方法修改成以下的樣,以由右往左的方式捲動背景圖:

XML
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 方法如下:

XML
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 支援遊戲程式製作的重要類別,做為開發遊戲程式的基礎知識。除此之外,我們也利用本文所介紹的類別實作一個簡單的遊戲程式,並令其具有能夠不斷捲動的背景圖案。下一回我們將會介紹更多的類別,讓讀者可以為所製作的遊戲程式加入更豐富的遊戲效果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值