第一部分:基礎知識(第一章)一個XNA 手機程式(續)

來源:互聯網
上載者:User

SpriteFont1.spritefont 這個檔案名稱起的實在不是十分生動。建議以它描述的實際字型來進行重新命名;如果您需要繼續使用預設字型設定,你可以將其重新命名為 Segoe14.spritefont。按右鍵檔案名稱並選擇屬性可以查看這個檔案的屬性——您可以看到該資產的名稱,也就是不帶副檔名的檔案名稱:Sagoe14。該資產名在程式中指向您所載入的字型。如果你將資產名更改成獨立於檔案名稱的名字,在將來的使用中你將會混淆,找不到你所對應的字型。

在初始階段,XNAHelloPhone項目包含2個C#代碼檔案:Program.cs和Game1.cs。第一個檔案非常簡單而且和Windows Phone 7遊戲程式絲毫無關!只有當定義了WINDOWS或XBOX標記之後,前置處理器指令才能啟用Program類。當編譯Windows Phone程式時,WINDOWS_PHONE標記取而代之。

對很多小遊戲來講,你幾乎會將所有時間都花費在Game1.cs檔案上。Game1類繼承自Game類,在其原始狀態它定義了2個欄位:graphics和spriteBatch。在這兩個欄位的基礎上我再增加三個:

XNA Project: XnaHelloPhone File: Game1.cs (excerpt showing fields)

namespace XnaHelloPhone

{

public class Game1 : Microsoft.Xna.Framework.Game

{

GraphicsDeviceManager graphics;

SpriteBatch spriteBatch;

string text = "Hello, Windows Phone 7!";

SpriteFont segoe14;

Vector2 textPosition;

}

}

這三個新的欄位簡單的指出了什麼樣的文本會顯示,顯示的字型以及文本在螢幕上顯示的位置。該位置是以相對於顯示屏的左上方的像素座標來指定的。Vector2結構有兩個欄位指定X和Y的浮點類型。出於效能方面的考慮,XNA的所有浮點值是單精確度的。(Silverlight 為雙精確度。)Vector2結構通常用於二維點、大小和甚至載體。

當遊戲在手機上運行時,Game1類被執行個體化,Game1的建構函式也被同時執行。標準代碼如下:

XNA Project: XnaHelloPhone File: Game1.cs (excerpt)

public Game1()

{

graphics = new GraphicsDeviceManager(this);

Content.RootDirectory = "Content";

// Frame rate is 30 fps by default for Windows Phone.

TargetElapsedTime = TimeSpan.FromTicks(333333);

}

第一條語句將圖形欄位(graphics field)初始化。在第二個語句中,內容(Content)是遊戲的屬性,它屬於ContentManager類型,RootDirectory是該類的屬性。將此屬性設定為"Content",這是符合當前儲存14point Segoe字型的內容目錄。第三條語句設定該程式的遊戲迴圈時間,它管理程式更新視頻顯示的頻率。Windows Phone 7螢幕重新整理頻率為每秒30幀。

Game1執行個體化後,在Game1執行個體中調用Run方法,遊戲類的基類啟動“遊戲啟動”的進程。第一個步驟之一是調用初始化(Initialize)方法,這一遊戲的衍生物可以重寫。XNA遊戲工作室自動產生架構方法,我沒有添加任何內容:

XNA Project: XnaHelloPhone File: Game1.cs (excerpt)

protected override void Initialize()

{

base.Initialize();

}

初始化方法不是載入字型或其他內容的地方。這是稍後時,基類調用LoadContent時的方法。

XNA Project: XnaHelloPhone File: Game1.cs (excerpt)

protected override void LoadContent()

{

spriteBatch = new SpriteBatch(GraphicsDevice);

segoe14 = this.Content.Load("Segoe14");

Vector2 textSize = segoe14.MeasureString(text);

Viewport viewport = this.GraphicsDevice.Viewport;

textPosition = new Vector2((viewport.Width - textSize.X) / 2,

(viewport.Height - textSize.Y) / 2);

}

在此方法中的第一個語句是系統自動提供的。您很快就會看到如何使用此spriteBatch對象來顯示子畫面(sprites)。

其他語句是我添加的,你會看到我傾向於用this這個關鍵詞作為Content和GraphicsDevice等屬性的首碼來提醒自己,他們是屬性而不是靜態類。如前所述,Content的屬性是ContentManager類型的。通用的 Load 方法允許載入Content到程式,在這種情況下Content的屬性是SpriteFont類型。用引號引起來的名稱是Content屬性中資產的名稱。此語句用來儲存載入在SpriteFont類型的segoe14欄位中的字型。

XNA中,子畫面(sprites)(包括文本字串)通常通過指定相對於左上方或相對於子畫面(sprites)左上方的像素座標來顯示。若要計算這些座標,最好知道螢幕大小和文本顯示時特定字型的大小。

SpriteFont類有一個測算大小非常方便的方法,名為MeasureString,以像素為單位返回Vector2對象與特定的文本字串的大小。(14磅的Segoe UI Mono字型,相當於18-2/3像素的高度,MeasureString調用後返回28的像素高度。)(For the 14-point Segoe UI Mono font, which has an equivalent height of 18-2/3 pixels, the MeasureString call returns a height of 28 pixels.)

XNA程式通常使用GraphicsDevice類的視區(Viewport)屬性來擷取螢幕的大小。這通過遊戲的GraphicsDevice屬性來訪問,並提供了寬度和高度屬性。

然後直接計算textPosition——與Viewport左上方相對應的座標(point)即為所顯示的文本字串的左上方。(It is then straightforward to calculate textPosition—the point relative to the upper-left corner of the viewport where the upper-left corner of the text string is to be displayed.)

到目前為止該程式的初始化階段已經完成,真正開始實質性的操作。程式進入遊戲迴圈。在以30 幀每秒重新整理率的視頻顯示同步過程中,程式中的兩種方法被不斷調用:更新(Update)接著繪製(Draw)不斷迴圈往複: 更新、 繪製、 更新、 繪製、更新、繪製……(如果每次Update方法需要超過1/30秒完成這個過程其實要比前面所述更加複雜,但我們將在後面幾章中詳細討論這些時序問題。)

Draw方法可以讓你在顯示屏上進行繪製。但這就是你想做的。如果您需要執行一些計算為繪圖做準備,你就應該先執行Update方法。Update方法是Draw方法的準備程式。很多時候XNA程式會基於使用者輸入來移動子畫面在顯示屏上的位置。對手機使用者來說,此使用者輸入主要涉及手指觸控螢幕幕。所有對使用者輸入的處理也應該在Update方法中執行。您將會在第3章中看到樣本。

你應該編寫您自己的Update和Draw方法,以便他們能儘快的執行。這點相當明顯,但我猜,有些非常重要的因素卻可能不是很明顯:

您應該避免Update和Draw的代碼定期從該程式的本地堆(heap?)中分配記憶體。(You should avoid code in Update and Draw that routinely allocates memory from the program’s local heap.)最終,.Net記憶體回收行程會收回部分此記憶體,而在記憶體回收行程做這個工作的時候,你的遊戲就可能會卡(your game might stutter a bit)。在關於XNA編程的章節中,您將可以看到如何來避免從堆(heap?)中分配記憶體。

您的Draw方法可能不會包含任何可疑的代碼;它通常潛伏在Update方法中從而導致各種麻煩。盡量避免涉及類的任何新的運算式。這些都將導致記憶體配置。執行個體化結構是可以的,不過(however有點奇怪,前後不象是轉折關係。Instantiating a structure is fine, however, because structure instances are stored on the stack and not in the heap.),因為結構執行個體化儲存在堆棧上,而不是堆(heap?)。(XNA在物件類型的定義中更多的使用結構而不是類,您經常需要在Update中建立。)但在沒有明確的新運算式的情況下,也可能發生堆(heap?)分配。例如,串連兩個字串就會在堆(heap?)上建立另一個字串。如果您需要在Update方法中巧妙的執行字串操作,則應使用StringBuilder。簡而言之,XNA提供使用StringBuilder對象顯示文本的方法。

然而,在XnaHelloPhone中,Update方法簡直微不足道。程式所顯示的文本固定在一個特定的位置。所有必要的計算也已在LoadContent方法中執行完畢。因此,無需對Update方法做任何改動,只需簡單的保留XNA 遊戲工作室最初建立其時候的樣子即可:

XNA Project: XnaHelloPhone File: Game1.cs (excerpt)

protected override void Update(GameTime gameTime)

{

if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)

this.Exit();

base.Update(gameTime);

}

預設代碼使用靜態遊戲台(GamePad)類檢查手機硬體的後退按鈕是否被按下,並使用此功能鍵離開遊戲。

最後,還有Draw方法。以下代碼為您建立的是單一背景色淡藍色的版本:

XNA Project: XnaHelloPhone File: Game1.cs (excerpt)

protected override void Draw(GameTime gameTime)

{

GraphicsDevice.Clear(Color.CornflowerBlue);

base.Draw(gameTime);

}

在XNA編程社區,一種名為CornflowerBlue的顏色成為其標誌性的顏色。當您開發一個XNA程式時,淡藍色螢幕的外觀是非常令人舒服的,因為這意味著程式如同已經使用過Draw方法一樣。

但如果您想要節省電源而在OLED上顯示的話,你會得到較暗的背景。在修改後的版本中,我妥協的將背景設定為深藍色。而在Silverlight中,XNA支援被視為標準的140個顏色。下面代碼執行後文本顯示為白色:

XNA Project: XnaHelloPhone File: Game1.cs (excerpt)

protected override void Draw(GameTime gameTime)

{

GraphicsDevice.Clear(Color.Navy);

spriteBatch.Begin();

spriteBatch.DrawString(segoe14, text, textPosition, Color.White);

spriteBatch.End();

base.Draw(gameTime);

}

顯示屏上的子畫面(Sprites)被捆綁成一個SpriteBatch對象,它在調用LoadContent時被建立出來。在調用開始(Begin)和結束(End)之間可以有多個調用DrawString來繪製文本和位元影像。這些是僅有的選項。此特定的索繩調用引用字型、 要顯示的文本、 螢幕上,和顏色的左上方相對於文本的左上方的位置。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.