圖形特效與文字顯示

摘要

使用 XNA Framework 設計遊戲程式的時候可以利用 SpriteBatch 類別提供的功能顯示遊戲的內容供使用者檢視,SpriteBatch 類別提供了豐富的功能協助遊戲程式繪製圖畫和文字,包括對所輸出的圖畫和文字加入特殊的效果,例如放大/縮小、旋轉、設定透明度、水平/垂直翻轉、以及圖層深度等遊戲程式常常需要表現的效果。在這一篇文件中,我們將會為大家介紹利用 SpriteBatch 類別為遊戲程式加上特殊效果的多種做法。

 認識 SpriteBatch 類別

XNA Framework 支援的 SpriteBatch 類別可以協助遊戲程式輸出 2 維的圖片和文字,並提供批次輸出的功能,避免頻繁地輸出遊戲的內容造成閃爍的現象。

[提示]

雖然以 XNA 為基礎的 3D 遊戲輸出 3 維的圖形內容時不需要依靠 SpriteBatch 類別提供的功能,但是當 3D 遊戲需要提供文字的功能選單供使用者選擇的時候,還是需要使用到 SpriteBatch 類別提供的文字輸出功能。

        表 1 所示為 SpriteBatch 類別常用的屬性

表 1 :SpriteBatch 類別常用的屬性
屬性名稱 說明
GraphicsDevice 取得遊戲程式所使用的 GraphicsDevic 類別的物件的屬性。

表 2 所示為 SpriteBatch 類別常用的方法:

表 2 :SpriteBatch 類別常用的方法
方法名稱 說明
Begin 宣告批次繪圖的動作開始。
Draw 繪製 2 維圖案。
DrawString 繪製文字。
End 宣告批次繪圖的動作結束,將從呼叫 Begin 方法之後繪製的所有內容輸出到遊戲視窗,並將 GraphicsDevice 的狀態還原到呼叫 Begin 方法之前的狀態。

SpriteBatch 類別的功能看似簡單,但是負責繪製 2 維圖案的 Draw 方法有高達7個不同的多載 (Overload) 版本,負責繪製文字的 DrawString 方法也有多達 6 個不同的多載版本,讓遊戲程式可以經由傳入不同數量的參數,控制方法執行的結果,如果再加計列舉型態的參數的內容值選擇,就可以組合出各種繁複的變化,滿足遊戲程式就變更遊戲程式內容的需求。

 SpriteBatch 類別與圖形特效支援

SpriteBatch 類別支援繪製 2 維圖案的 Draw 方法一共有以下 7 個不同的多載版本:

SpriteBatch.Draw(texture, destinationRectangle, color)

SpriteBatch.Draw(texture, destinationRectangle, sourceRectangle, color)

SpriteBatch.Draw(texture, destinationRectangle, sourceRectangle, color,

rotation, origin, effects, layerDepth)

SpriteBatch.Draw(texture, position, color)

SpriteBatch.Draw(texture, position, sourceRectangle, color)

SpriteBatch.Draw(texture, position, sourceRectangle, color, rotation,

origin, scale, effects, layerDepth)

SpriteBatch.Draw(texture, position, sourceRectangle, color, rotation,

origin, scale, effects, layerDepth)

        其需要用到的參數請參考表3的詳細說明:

表 3 :SpriteBatch 類別的 Draw 方法需要使用的參數
參數名稱 說明
texture 型態為 Texture2D 類別的參數,負責管理欲繪製的 2 維圖案。
destinationRectangle 負責描述欲繪製在遊戲視窗上的物體的矩形。
color 負責控制欲繪製的圖形的色調的參數,傳入 Color.White 表示不改變欲顯示的物體的色調。
sourceRectangle 指定欲用來取用來源物件的矩形。
scale 圖案放大/縮小的倍數。
rotation 旋轉角度。
origin 旋轉圖形時所依據的圓心。
effects 設定成 SpriteEffects.FlipHorizontally 表示要水平翻轉圖案,設定成 SpriteEffects.FlipVertically 表示要垂直翻轉圖案。
layerDepth 圖層深度。0 代表前景層,1 代表背景層,可以搭配呼叫 SpriteBatch 類別的 Begin 方法傳入的 SpriteSortMode 參數控制是否要對欲繪製的內容依 layerDepth 的內容值排序。
position 指定欲繪製的圖案的左上角點座標。

光是靠 SpriteBatch 類別的 Draw 方法的眾多參數,就能夠創造繁複的遊戲效果,例如透過 color 參數設定圖案的色調和透明度,透過 rotation 參數指定旋轉圖案的角度,利用 origin 參數設定圖案旋轉的圓心座標,利用 effects 參數水平翻轉或垂直翻轉圖案,利用 scale 參數指定放大/縮小圖案的倍數,或是利用 layerDepth 參數設定圖案要顯示在那一個圖層。

要利用 SpriteBatch 類別的 Draw 方法的各個參數創造繁複的遊戲效果,首先請啟動 Visual Studio 2010 Express for Windows Phone,並建立 [Windows Phone Game(4.0)] 型態的專案,然後將遊戲程式欲顯示的圖案加入到 Content Pipeline 專案,以便讓遊戲程式載入顯示。

要為欲顯示的圖案加入各種不同的特殊效果,請先於 Game1 類別中宣告以下的變數,負責管理欲顯示的圖案,以及圖案的顯示的位置:

 

XML
Texture2D Mario;									//管理欲顯示的圖案的變數
Vector2 MarioPosition;								//存放圖案顯示的位置的變數

 

然後將Game1類別的建構函式編輯成以下的樣子,負責設定遊戲視窗的高度和寬度:

XML
public Game1()
{
    graphics = new GraphicsDeviceManager(this);
    Content.RootDirectory = "Content";
    graphics.PreferredBackBufferHeight = 800;				//設定遊戲視窗的高度為800
    graphics.PreferredBackBufferWidth = 480;				//設定遊戲視窗的寬度為480
    TargetElapsedTime = TimeSpan.FromTicks(333333);
}

 

設定妥遊戲視窗的高度和寬度之後請編輯 Game1 類別的 LoadContent 方法,負責載入遊戲程式欲使用的資源,編輯好的 LoadContent 方法如下:

XML
protected override void LoadContent()
{
    spriteBatch = new SpriteBatch(GraphicsDevice);
    Mario = Content.Load<Texture2D>("Mario");	  //從Content Pipeline專案載入欲顯示的圖案
MarioPosition = new Vector2(0, 0);            //設定圖案要顯示在遊戲視窗的最左上角
}

 

最後我們只要在 Game1 類別的 Draw 方法中呼叫 SpriteBatch 的 Draw 方法,傳入適當的參數,就可以顯示出各種特殊的效果,例如以下的 Draw 方法便會旋轉、放大/縮小、水平/垂直翻轉、改變圖案色調、以及設定圖案的透明度:

XML
protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.CornflowerBlue);
    spriteBatch.Begin();			                      	//宣告批次繪圖動作開始

    spriteBatch.Draw(Mario, MarioPosition, Color.White);	//顯示未加上特殊效果的圖案
    spriteBatch.Draw(Mario, new Vector2(MarioPosition.X + Mario.Width*2, MarioPosition.Y 
+ Mario.Height), null, Color.White, MathHelper.ToRadians(180), new Vector2(0, 0), 1, SpriteEffects.None, 0);						//將圖案旋轉180度
    spriteBatch.Draw(Mario, new Vector2(MarioPosition.X + Mario.Width * 2, 0), null, 
Color.White, 0, new Vector2(0, 0), 1, 
SpriteEffects.FlipHorizontally, 0);						//將圖案水平翻轉

    spriteBatch.Draw(Mario, new Vector2(MarioPosition.X , MarioPosition.Y + Mario.Height), 
Color.Red);								//以紅色的色調顯示圖案
spriteBatch.Draw(Mario, new Vector2(MarioPosition.X + Mario.Width, MarioPosition.Y + 
Mario.Height), Color.Blue);					//以藍色的色調顯示圖案
    spriteBatch.Draw(Mario, new Vector2(MarioPosition.X + Mario.Width * 2, MarioPosition.Y 
+ Mario.Height), Color.Green);					//以綠色的色調顯示圖案

    spriteBatch.Draw(Mario, new Vector2(MarioPosition.X, MarioPosition.Y + 
Mario.Height*2), null, Color.White, 0, new Vector2(0, 0), 1, 
SpriteEffects.None, 0);						//以圖案原始大小顯示圖案
    spriteBatch.Draw(Mario, new Vector2(MarioPosition.X + Mario.Width, MarioPosition.Y + 
Mario.Height * 2), null, Color.White, 0, new Vector2(0, 0), 0.5f, SpriteEffects.None, 0);	//以原圖一半的大小顯示圖案
spriteBatch.Draw(Mario, new Vector2(MarioPosition.X + Mario.Width*1.5f, 
MarioPosition.Y + Mario.Height * 2), null, Color.White, 0, new Vector2(0, 0), 2, SpriteEffects.None, 0);						//以原圖兩倍的大小顯示圖案

    spriteBatch.Draw(Mario, new Vector2(MarioPosition.X, MarioPosition.Y + 
Mario.Height*4), null, new Color(255, 255, 255, 255), 0, new Vector2(0, 0), 1, SpriteEffects.None, 0);						    //以原始透明度顯示圖案
spriteBatch.Draw(Mario, new Vector2(MarioPosition.X + Mario.Width, MarioPosition.Y + 
Mario.Height * 4), null, new Color(255, 255, 255, 170), 0, new Vector2(0, 0), 1, SpriteEffects.None, 0);						 //以約2/3的透明度顯示圖案
spriteBatch.Draw(Mario, new Vector2(MarioPosition.X + Mario.Width*2, MarioPosition.Y 
+ Mario.Height * 4), null, new Color(255, 255, 255, 85), 0, new Vector2(0, 0), 1, SpriteEffects.None, 0);					//以約1/3的透明度顯示圖案

    spriteBatch.End();								    //宣告批次繪圖動作結束
base.Draw(gameTime);
}

 

做好之後請執行專案,您就會看到如圖1的畫面,看到傳入不同的參數內容給 SpriteBatch 類別的 Draw 方法顯示的內容的結果:

圖1:傳入不同的參數內容控制SpriteBatch類別的Draw方法顯示的內容的結果

註:本文所使用的人物圖案來源來自:http://www.emutalk.net/showthread.php?t=43273

[說明]

呼叫 SpriteBatch 類別的 Draw 方法執行旋轉圖案的時候而要傳入的旋轉角度的單位是弳度量,而不是慣用的度度量。以 XNA 為基礎的遊戲程式可以利用 MathHelper 類別的 ToRadians 方法指定的度度量角度轉換成弳度量,再交給 SpriteBatch 類別的 Draw 方法執行旋轉圖案的動作。

MathHelper 類別是 XNA Framework 中提供高效能數學運算功能的類別,負責提供遊戲執行時需要的數學運算。有關 MathHelper 類別常用的屬性可以參考表 4 的說明:

表 4 :MathHelper 類別常用的屬性
屬性名稱 說明
E 代表數學上的指數常數 e (亦稱歐拉數 – Euler's Number )。
Log10E 代表以 10 為基底的對數 e 。
Log2E 代表以 2 為基底的對數 e 。
Pi 代表圓周率(pi)。
PiOver2 代表/2。
PiOver4 代表/4。
TwoPi 代表2。

MathHelper 類別常用的方法請參考表 5 的說明:

表 5:MathHelper 類別常用的方法
方法名稱 說明
Clamp 限制數值必須介於指定的數值範圍。
Distance 計算兩個數值之間的距離。
Hermite 執行 Hermite Spline 內插法。
Lerp 於兩點之間執行線性內插。
Max 取得兩個數值中較大者的內容值。
Min 取得兩個數值中較小者的內容值。
SmoothStep 利用 cubic 方程式計算兩個數值間的內插值。
ToDegrees 將弳度量轉換成度度量。
ToRadians 將度度量轉換成弳度量。
WrapAngle 限制角度必須介於π和-π之間。

[提示]

您只要善用 Game1 類別的 Update 方法,動態更新傳遞給 SpriteBatch 類別的 Draw 方法的參數內容值,就可以很容易地令所開發的遊戲程式動態旋轉圖案、動態放大/縮小圖案、或是動態令圖案逐漸變成透明/不透明。

 SpriteBatch 類別與文字輸出支援

SpriteBatch 類別除了能夠執行顯示圖案的功能以下,還能夠協助遊戲程式顯示文字,當遊戲程式需要顯示功能表供使用者選擇,或是需要顯示遊戲的狀態(包括分數和遊戲的關卡)時,就會需要使用到 SpriteBatch 類別支援顯示文字的功能。

遊戲程式可以利用 SpriteBatch 類別的 DrawString 方法執行顯示文字的動作,和 Draw 方法支援多種多載版本一樣,SpriteBatch 類別支援的 DrawString 方法一共有以下 6 個不同的多載版本:

SpriteBatch.DrawString(spriteFont, text, position, color)

SpriteBatch.DrawString(spriteFont, text, position, color, rotation, origin, scale,

effects, layerDepth)

SpriteBatch.DrawString(spriteFont, text, position, color, rotation, origin,

scale, effects, layerDepth)

SpriteBatch.DrawString(spriteFont, text, position, color)

SpriteBatch.DrawString(spriteFont, text, position, color, rotation, origin,

scale, effects, layerDepth)

SpriteBatch.DrawString(spriteFont, text, position, color, rotation, origin,

scale, effects, layerDepth)

        其需要用到的參數請參考表6的詳細說明:

表 4 :SpriteBatch 類別的 DrawString 方法需要使用的參數
參數名稱 說明
spriteFont 型態為 SpriteFont 類別的參數,負責記錄欲輸出的文字的定義。
text 欲輸出的文字,其型態可以是 String 類別或 StringBuilder 類別。
position 指定欲輸出的文字的左上角點座標。
color 負責控制欲輸出的文字的色調的參數,傳入 Color.White 表示不改變欲顯示的文字的色調。
rotation 依據輸出的文字的圓心旋轉 2 維輸出的文字。
origin 旋轉文字時所依據的圓心。
scale 文字放大/縮小的倍數。
effects 設定成 SpriteEffects.FlipHorizontally 表示要水平翻轉所顯示的文字,設定成 SpriteEffects.FlipVertically 表示要垂直翻轉所顯示的文字。
layerDepth 圖層深度。0 代表前景層,1 代表背景層,可以搭配呼叫 SpriteBatch 類別的 Begin 方法傳入的 SpriteSortMode 參數控制是否要對欲繪製的內容依 layerDepth 的內容值排序。

[提示]

呼叫 SpriteBatch 類別的 DrawString 方法需要的參數和 Draw 方法需要的參數幾乎完全相同,所代表的意義和使用方式也都一樣。

了解 SpriteBatch 類別的 DrawString 方法的基本功能之後,接下來我們就要為遊戲程式加入顯示文字的功能。

要顯示文字,請先使用滑鼠的右鍵點中 [Solution Explorer] 視窗中的 Content Pipeline 專案名稱,再從出現的功能表選擇 [Add | New Item] 功能,螢幕上就會出現如圖 2 的畫面,要求您選擇欲新增的資源項目:

圖 2:要求選擇欲新增的資源項目的畫面

請於中間視窗選擇 [Sprite Font] 項目,於 [Name] 欄位輸入字型定義檔案的名稱,做好之後按下 [Add] 鍵,執行新增 SpriteFont 資源到 Content Pipeline 專案的動作,Visual Studio 2010 Express for Windows Phone 就會為 Content Pipeline 專案加入字型定義檔案,其內容如下:

 

<?xml version="1.0" encoding="utf-8"?>
<!--
This file contains an xml description of a font, and will be read by the XNA
Framework Content Pipeline. Follow the comments to customize the appearance
of the font in your game, and to change the characters which are available to draw
with.
-->
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
  <Asset Type="Graphics:FontDescription">
    <!--
    Modify this string to change the font that will be imported.
    -->
    <FontName>Segoe UI Mono</FontName>
    <!--
    Size is a float value, measured in points. Modify this value to change
    the size of the font.
    -->
    <Size>14</Size>
    <!--
    Spacing is a float value, measured in pixels. Modify this value to change
    the amount of spacing in between characters.
    -->
    <Spacing>0</Spacing>
    <!--
    UseKerning controls the layout of the font. If this value is true, kerning information
    will be used when placing characters.
    -->
    <UseKerning>true</UseKerning>
    <!--
    Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic",
    and "Bold, Italic", and are case sensitive.
    -->
    <Style>Regular</Style>
    <!--
    If you uncomment this line, the default character will be substituted if you draw
    or measure text that contains characters which were not included in the font.
    -->
    <!-- <DefaultCharacter>*</DefaultCharacter> -->
    <!--
    CharacterRegions control what letters are available in the font. Every
    character from Start to End will be built and made available for drawing. The
    default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin
    character set. The characters are ordered according to the Unicode standard.
    See the documentation for more information.
    -->
    <CharacterRegions>
      <CharacterRegion>
        <Start>&#32;</Start>
        <End>&#126;</End>
      </CharacterRegion>
    </CharacterRegions>
  </Asset>
</XnaContent>

 

您可以利用 <FontName> 標籤指定欲顯示的文字所使用的字型,利用 <Size> 標籤指定欲顯示的文字的字型大小,利用 <Style> 標籤設定字型的樣式,包括 Bold (粗體)和 Italic (斜體),利用 <CharacterRegion> 標籤指定欲顯示的文字範圍,包括利用 <Start> 標籤定義欲顯示的字元中第一個字元的 Unicode ,利用 <End> 標籤定義欲顯示的字元中最後一個字元的 Unicode 。例如以下就是一個 SpriteFont 字型定義檔的範例,指定欲使用大小為 18 的 Courier New 粗體字型,而且開頭字元為 a,結束字元為 z:

<?xml version="1.0" encoding="utf-8"?>
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
  <Asset Type="Graphics:FontDescription">
    <FontName>Courier New</FontName>
    <Size>18</Size>
    <Spacing>0</Spacing>
    <UseKerning>true</UseKerning>
    <Style>Bold</Style>
    <CharacterRegions>
      <CharacterRegion>
        <Start>a</Start>
        <End>z</End>
      </CharacterRegion>     
  </Asset>
</XnaContent>

 

[注意]

請注意 SpriteFont 字型定義檔是一個內容大小寫視為相異的 XML 文件,編輯字型定義的時候請特別注意大小寫不要寫錯。除此之外,如果遊戲程式需要顯示中文字元,因為中文字元的 Unicode 內容值並不一定會連續,所以我們必須為每一個欲顯示的中文字定義一個 <CharacterRegion> 段落,例如以下的字型定義,便會指定遊戲程式可以顯示 [中文]這兩個中文字:

<CharacterRegions>
      <CharacterRegion>
        <Start>中</Start>
        <End>中</End>
      </CharacterRegion>
      <CharacterRegion>
        <Start>文</Start>
        <End>文</End>
      </CharacterRegion>
</CharacterRegions>

 

定義好遊戲程式欲顯示的中文字型定義之後,就可以利用 SpriteFont 類別提供的功能管理遊戲程式欲顯示的字型。SpriteFont 類別常用的屬性可以參考表 5 的說明:

表 5:SpriteFont 類別常用的屬性
屬性名稱 說明
Characters 取得 SpriteFont 類別的物件管理的所有字元。
DefaultCharacter 指定預設字元。如果 DefaultCharacter 屬性的內容值設定為異於 null 的內容值,則當遊戲程式欲顯示 SpriteFont 字型定義檔中未定義的字元時,就會自動顯示 DefaultCharacter 屬性指定的字元。如果 DefaultCharacter 屬性的內容值設定為 null,則當遊戲程式欲顯示 SpriteFont 字型定義檔中未定義的字元時,就會引發例外。

表 6 所示為 SpriteFont 類別常用的方法:

表 6:SpriteFont 類別常用的方法
方法名稱 說明
MeasureString 傳回 SpriteFont 字型定義檔定義的文字的高度與寬度。當遊戲程式欲將文字顯示在某個矩形的正中央的時候就需要用到這個方法。

準備好必要的字型定義檔之後,接下來我們就要為遊戲程式加入顯示文字的功能。

首先請於 Game1 類別加入以下的變數宣告,負責管理欲顯示的文字,文字顯示的位置,文字旋轉的角度,以及旋轉的圓心座標:

 

XML
SpriteFont GameFont;									//管理欲顯示的文字的變數
Vector2 FontPosition;								//管理文字顯示位置的變數
Vector2 RotateOrigin;						//管理旋轉文字依據的圓心座標的變數
float FontAngle = 0;									//管理文字旋轉角度的變數

 

然後於 Game1 類別的 LoadContent 方法加入以下的程式碼,負責載入欲顯示的文字定義,計算欲顯示的文字的大小,位置,以及旋轉時的圓心座標:

XML
Viewport ViewPort = GraphicsDevice.Viewport;					//取得遊戲視窗的大小
GameFont = Content.Load<SpriteFont>("GameFont");	             //載入欲顯示的文字資源
Vector2 FontSize = GameFont.MeasureString("中文");			//計算欲顯示的文字的大小
FontPosition = new Vector2((ViewPort.Width - FontSize.X) / 2, 
(ViewPort.Height - FontSize.Y) / 2);  //設定文字要顯示在遊戲視窗的正中央
RotateOrigin = new Vector2(FontSize.X / 2, FontSize.Y / 2);//設定文字的中心為旋轉的圓心

 

[注意]

呼叫 Content 物件的 Load 方法載入 Content Pipeline 專案管理的字型資源時所傳入的參數名稱即副檔名為 .spritefont 的字型定義檔的主檔名,也就是圖 2 所示加入字型資源的畫面中於 [Name] 欄位輸入的檔案名稱中的主檔名。

載入妥遊戲程式欲顯示的文字資源之後,請將 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();
    if (FontAngle < 360)							//如果旋轉角度尚未到達360度
    {
        FontAngle += 1;									//遞增旋轉角度1度
    }
    // TODO: Add your update logic here
    base.Update(gameTime);
}

 

最後我們只要在 Game1 類別的 Draw 方法中呼叫 spriteBatch 物件的 End 方法之前加入以下的程式碼,負責顯示字型定義檔中指定的中文字,並以文字中心點為圓心旋轉所顯示的文字

XML
spriteBatch.DrawString(GameFont, "中文", FontPosition+RotateOrigin, Color.White, 
MathHelper.ToRadians(FontAngle), RotateOrigin, 1, SpriteEffects.None, 
0);		//呼叫SpriteBatch類別的DrawString方法顯示並依據指定的角度旋轉文字

 

做好之後請執行專案,您將會看到遊戲程式顯示的中文出現在遊戲視窗的正中央,並以文字的中心點為圓心進行旋轉的情形,如圖 3 所示:

圖 3:顯示並旋轉中文字的遊戲程式執行的情形

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值