显示文字与输入

来源:互联网 发布:bindvalue数组 编辑:程序博客网 时间:2024/04/30 10:11

學會貼圖後,接著就來試試看顯示文字。一般來說 XNA 內的文字其實都是圖,要顯示那些字就必須有那些字的圖檔才行,而 XNA 也有方便產生文字圖檔的方法。收先在 Content 專案上按滑鼠右鍵,選擇加入新物件

然後選擇 Sprite Font

這就是 XNA 內建的字型物件,我們給他取名叫做 DefaultFont。產生後會開啟此檔,其實他只是一個 xml 檔案,描述我們要用哪種字型與那些字,重要的元素有:

VB
<FontName>Segoe UI Mono</FontName>

用來指定要使用的字型,必須是電腦內存在的字型,我們不必擔心手機上沒有此字型,因為 XNA 會將它轉換成圖檔。

 

VB
<Size>14</Size>

設定字型大小。

 

VB
<Spacing>0</Spacing>

每個字之間要空多大的空間。

 

VB
<UseKerning>true</UseKerning>

是不是要用此字型內建的字距。

 

VB
<Style>Regular</Style>

選擇樣式,"Regular", "Bold", "Italic"

 

<CharacterRegions>  <CharacterRegion>    <Start>&#32;</Start>    <End>&#126;</End>  </CharacterRegion></CharacterRegions>

這是最重要的元素,用來指示會用到那些字,CharacterRegions 裡面可以有很多組 CharacterRegion,每一組 CharacterRegion 包含一個 Start 和一個 End,表示文字的開始與結束。如果你知道文字的代碼,可以直接寫代碼,但要在號碼前面加上 ”&#”、號碼後面加上 ”;”,號碼用十進位表示。如果你不知道代碼也沒關係,可以直接打文字,像是這樣:

 

<CharacterRegions>  <CharacterRegion>    <Start> </Start>    <End>~</End>  </CharacterRegion></CharacterRegions>

空格代碼是 32,”~” 代碼是 126。這裡使用的代碼是 Uft-8,也表示它可以顯示多國語言。

還有另外一個元素被註解起來

VB
<DefaultCharacter>*</DefaultCharacter>

這是用來設定如果出現不能顯示的字時,要出現的符號。

接著就來顯示些文字試試看,

SpriteFont Font;protected override void LoadContent() {    spriteBatch = new SpriteBatch(GraphicsDevice);    Airplane = Content.Load<Texture2D>("Airplane");    Font = Content.Load<SpriteFont>("DefaultFont");}protected override void Draw(GameTime gameTime) {    GraphicsDevice.Clear(Color.CornflowerBlue);    spriteBatch.Begin();    spriteBatch.Draw(Airplane, Vector2.Zero, Color.White);    spriteBatch.DrawString(Font, "Test string", new Vector2(100, 100), Color.Black);    spriteBatch.End();    base.Draw(gameTime);}

先宣告文字物件 SpriteFont,接著一樣在 LoadContent 載入文字物件,最後在 Draw 函式呼叫 DrawString 畫出文字。範例執行結果如下圖

SpriteBatch.DrawString 有五種多載,

VB
DrawString(SpriteFont spriteFont, string text, Vector2 position, Color color);-------------------------------------------------------------------------------------------------------------DrawString(SpriteFont spriteFont, StringBuilder text, Vector2 position, Color color);-------------------------------------------------------------------------------------------------------------DrawString(SpriteFont spriteFont, string text, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects effects, float layerDepth);-------------------------------------------------------------------------------------------------------------DrawString(SpriteFont spriteFont, string text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth);----------------------------------------------------------------------------------------------------------------DrawString(SpriteFont spriteFont, StringBuilder text, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects effects, float layerDepth);----------------------------------------------------------------------------------------------------------------DrawString(SpriteFont spriteFont, StringBuilder text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth);----------------------------------------------------------------------------------------------------------------

其實仔細看看會發現和貼圖的參數很像,text 是我們要顯示的文字、position 是顯示的位置,預設值也是從文字的左上角為原點、color 是文字的顏色、rotetion 為旋轉角度、origin 是文字的原點、scale 是縮放比例、effects 和貼圖一樣只有兩種鏡射而已、layerDepth 試圖層深度。有了貼圖的觀念,在這裡應該不會有甚麼問題。

在此介紹一個滿容易用到的功能,當我們指定顯示位置時,不會想要對齊圖片的左上角,通常會想要對齊中心點,因此就會設定 origin,如果是圖片,要知道中心點很容易,長寬除以二就好,但是對於文字,尤其是不確定內容的文字就很無法事先得知長寬了,這裡可以用 SpriteFont.MeasureString 函式來取得長寬,輸入要顯示的文字字串,他會回傳一個 Vector2 結構,用來表示此字串的長與寬。 我們來看一個例子

string TestString = "Test string";protected override void Draw(GameTime gameTime) {    GraphicsDevice.Clear(Color.CornflowerBlue);    // TODO: Add your drawing code here    spriteBatch.Begin();    spriteBatch.Draw(Airplane, new Vector2(100, 130), null, Color.White, 0, new Vector2(20, 17.5f), 1, SpriteEffects.None, 0);    spriteBatch.DrawString(Font, TestString, new Vector2(100, 100), Color.Black, 0, Font.MeasureString(TestString) / 2, 1, SpriteEffects.None, 0);    spriteBatch.DrawString(Font, TestString, new Vector2(100, 160), Color.Black);    spriteBatch.End();    base.Draw(gameTime);}

產生一個變數存放我們要顯示的字串,讓飛機顯示在 100,130 的地方做標記,當然,飛機設定 origin 為 Vector2 (20, 17.5f),所以會以中心點為原點。第一個顯示文字有設定 origin,用 SpriteFont.MeasureString 取得長寬後直接除以二,用來設定中心點為原點,顯示在座標 (100, 100) 的地方。第二個文字就沒有給 origin 參數,讓他直接顯示在座標 (100, 160) 的地方,這兩個字串的 X 軸相同,Y 軸不同,所以應該只會有上下不同行而已,但是因為 origin 參數的關係,讓第一組文字置中了。下面是此範例的畫面。

了解如何顯示文字後,讓我們試試看輸入文字,在 Silverlight 裡要輸入文字只要放入 TextBox 就可以,點擊 TextBox 就會自動跑出虛擬鍵盤,但 是XNA 沒有 TextBox 控制項,要讓使用者輸入文字的話就要透過函式呼叫的方法。來看個範例:

string InpuText = null;protected override void Update(GameTime gameTime) {    // Allows the game to exit    if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)        this.Exit();    if (InpuText == null && Guide.IsVisible == false) {        Guide.BeginShowKeyboardInput(PlayerIndex.One, "標題", "說明文字", "Default text", new AsyncCallback((ar) => {            InpuText = Guide.EndShowKeyboardInput(ar);        }), null);    }    base.Update(gameTime);}protected override void Draw(GameTime gameTime) {    GraphicsDevice.Clear(Color.CornflowerBlue);    // TODO: Add your drawing code here    spriteBatch.Begin();    spriteBatch.Draw(Airplane, new Vector2(100, 130), null, Color.White, 0, new Vector2(20, 17.5f), 1, SpriteEffects.None, 0);    spriteBatch.DrawString(Font, TestString, new Vector2(100, 100), Color.Black, 0, Font.MeasureString(TestString) / 2, 1, SpriteEffects.None, 0);    spriteBatch.DrawString(Font, TestString, new Vector2(100, 160), Color.Black);    if (InpuText != null) {        spriteBatch.DrawString(Font, InpuText, new Vector2(100, 200), Color.Green);    }    spriteBatch.End();    base.Draw(gameTime);}

先增加一個存放輸入文字的變數,接著在 Update 內呼叫 Guide.BeginShowKeyboardInput 函式就可以跑出虛擬鍵盤讓使用者輸入,呼叫的時候要注意,因為顯示虛擬鍵盤時,整個遊戲的迴圈依然在進行中,所以要加上 Guide.IsVisible == false 的判斷來決定是否呼叫 Guide.BeginShowKeyboardInpu。

Guide.BeginShowKeyboardInpu 的參數很簡單,第一個是 PlayerIndex 列舉,一定要輸入 PlayerIndex.One、第二個參數是標題、第三個參數是說明、再來是預設的內容、接著是回呼函式、最後是要帶入回呼函式的物件。而另一個多載只是在最後多一個使用密碼模式的選擇,輸入 true 的話就變成輸入密碼的樣式。

而輸入完成後,會呼叫回呼函式,我們必須叫用 Guide.EndShowKeyboardInput 來取得使用者輸入的文字。

由 Guide 顯示的視窗是使用手機內建的控制項,和遊戲不相關,所以才會使用到回呼的方式,也因此裡面的標題和說明等文字可以直接輸入,不用在 XNA 裡的 SpriteFont 加入,但是當我們要讓回傳的文字顯示在畫面上的話就需要用 XNA 的文字顯示方式了! 

Guide 這個物件另一個常用到的功能就是顯示 MessageBox。 

 

bool NeedShowMessage = false;protected override void Update(GameTime gameTime) {    // Allows the game to exit    if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)        this.Exit();    if (InpuText == null && Guide.IsVisible == false) {        Guide.BeginShowKeyboardInput(PlayerIndex.One, "標題", "說明文字", "Default text", new AsyncCallback((ar) => {            InpuText = Guide.EndShowKeyboardInput(ar);            NeedShowMessage = true;        }), null);    }    if (NeedShowMessage == true && Guide.IsVisible == false) {        Guide.BeginShowMessageBox("Title", "TEXT", new string[] { "Yes", "No" }, 0, MessageBoxIcon.Alert, (ia) => {            int? ansIndex = Guide.EndShowMessageBox(ia);            InpuText += string.Format(" and you choose " + ansIndex);        }, null);        NeedShowMessage = false;    }    base.Update(gameTime);}

我們增加一個判斷要不要顯示 MessageBox 的變數 NeedShowMessage,當我們輸入完文字的時候,就顯示 MessageBox。 方式也很簡單,呼叫 Guide.BeginShowMessageBox 即可,第一個參數是標題、第二個參數是內容、第三個參數必須是一個 string 的陣列,用來表示按鈕上的文字,最少一個最多兩個、第四個參數是設定預設按鈕、下一個參數是決定此 MessageBox 是何種功能,有四種狀態None、Error、 Warning、Alert,這四種設定會影響彈出訊息時的聲音、再來是回呼函式、最後就是要傳給回呼函式的物件。 和輸入相同的是當使用者按下按鈕後,Guide 會呼叫回呼函式,我們要用 Guide.EndShowMessageBox 來取得使用者按下的按鈕,如果使用者是按手機上的 Back 鍵取消 MessageBox,那就會回傳 null。

原创粉丝点击