邊做邊學 XBOX 遊戲開發系列 2 - 使用 Xbox 360 控制器,進行輸入控制

[觀看教學文章]  [下載影片及範例資料]


程式引導手冊二 – 使用 Xbox 360 控制器,進行輸入控制

在程式引導手冊一當中,已經跟各位介紹,如何在程式中顯示圖片以及顯示文字。接下來,在第二個引導手冊中,主要是介紹如何做圖片的移動,並將分為兩個部份,第一個部份會說明如何讓圖片移動,第二部分將會切入主題,使用 Xbox 360 的控制器控制圖片移動。圖一為本次範例要控制移動的圖片。


圖一、引導手冊二所使用的圖片

根據引導手冊一所述,現在你可以將上圖的圖片在程式中顯示出來,如圖二。


圖二、將圖片在程式中顯示。

在 SpriteBatch.Draw (Texture2D, Vector2,Color) 的第二個參數中,在前面跟各位介紹過,主要是用來決定貼圖的位置,你可以隨意指定視窗中的任何位置顯示圖片。例如:

spriteBatch.Draw(pic, new Vector2(100,50), Color.White);

上述程式碼,會將貼圖位置指定在視窗中的 (100, 50) 的點上。

我們可以用變數的方式來取代,上述程式碼的第二個參數。在 Game1 的類別的空白處宣告一個 Vector2 的變數,該變數的用途為儲存圖片的位置,如下列程式碼。

public class Game1 : Microsoft.Xna.Framework.Game
    {
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;
    Texture2D pic;
    Vector2 position;

完成上述操作以後,你可以在建構子當中初始化變數,如下

position = new Vector2(100,50);

在 Draw 的函數中,我們將 SpriteBatch.Draw 的第二個參數改成 position,如下

spriteBatch.Draw(pic, position, Color.White);

按下 F5 進行編譯及執行,可以看到如圖三的畫面


圖三、將圖片用參數的方式指定位置

現在我們要讓圖片移動的話,我們將程式碼做些簡單的修改,我們在 Update 的函數中,加入以下程式碼

position.X += 1;
position.Y += 1;

Position 是個二維的座標,所以你可以針對 X 軸或 Y 軸給值或是做運算。程式碼如下面程式碼所示

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
    position.X += 1;
    }

執行後可以發現圖片會開始向右邊平移。

執行一陣子過後,你可能會發現圖片會跑出視窗,然後就看不到圖片。如果要圖片移動只能在視窗中的話,那我們首先就需要先取得視窗的大小。第一步先宣告兩個參數 width 和 height,然後在建構子當中取得現在視窗的大小,程式碼如下所示。

public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Texture pic;
        Vector2 position;
        int width;
        int height;
        public Game1()
        {
            graphic = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            position = new Vector2(100, 50);
            width = graphics.PreferredBackBufferWidth;
            Height = graphics.PreferredBackBufferHeight;
        }

在 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 (position.X < (width – pic.Width))
        {
            position.X += 1;
        }
        base.Update(gameTime);
    }

在上述程式碼中,可以看見在 Updata 函數中,有一個條件式,主要的意義是說 "如果現在圖片的位置小於視窗的寬度,則將圖片的 X 位置加 1"。可能你會很好奇為什麼在條件式中需要將視窗的寬度減掉圖片的寬度?原因是,在 XNA 中的圖片座標位置,是以圖片的左上角當作參考。如果不將視窗寬度減掉圖片的寬度的話,這樣還是會發生圖片移動到外面的情況。

完成上述操作以後,當你編譯執行後,可以看見圖片的移動,同時,當圖片移動到視窗邊界時,會停住不動。接下來就要跟各位介紹如何使用 Xbox360 的控制器移動圖片。

Xbox 360 控制器如圖四。


圖四、Xbox 360 的控制器

你可以在這裡 (https://www.microsoft.com/taiwan/hardware/gaming/ProductDetails.aspx?pid=091) 獲得更多的資訊。

在程式碼的空白位置我們需要宣告 GamePadState 物件,如下面程式碼,這個物件用來儲存控制鍵的按鈕狀態。

public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Texture2D pic;
        Vector2 position;
        int width;
        int height;
        GamePadState gps;

首先,先了解一下 GamePadState 有那些常用的屬性和方法,如表一。

屬性 說明
IsConnected 用來檢查現在是否控制器已經連接。
ThumbSticks 可以用來取出左邊或是右邊的類比搖桿的 X、Y 數值,而數值範圍介於 -1 到 +1 之間的浮點數。
方法 說明
IsButtonDown(Buttons) 用來檢查傳入的 Button 是否被壓下。
IsButtonUp(Buttons) 用來檢查傳入的 Button 是否被放開。

瞭解了GamePadState 一些常用的屬性跟方法以後,在程式碼中的建構子宣告以下程式碼,給 GamePadState 初始值。

gps = GamePad.GetState(PlayerIndex.One);

上述程式碼是用來,取出第一個使用者的控制器狀態 。如果需要取出第二個使用者的控制器狀態,則將 GetState 函數中的 PlayerIndex.One 改成 PlayerIndex.Two,在遊戲中最多可以有四個控制器做操作。

在 Update 的函數中,寫入以下程式碼

if (gps.IsConnected)
    {
         gps = GamePad.GetState(PlayerIndex.One);
    
         if (gps.ThumbSticks.Left.X > 0 && position.X < (width-pic.Width))
         {
             position.X += 1;
         }
         if (gps.ThumbSticks.Left.X < 0 && position.X > 0)
         {
             position.X -= 1;
         }
         if (gps.ThumbSticks.Left.Y < 0 && position.Y < (height-pic.Height))
         {
             position.Y += 1;
         }
         if (gps.ThumbSticks.Left.Y > 0 && position.Y > 0)
         {
             position.Y -= 1;
         }
    }

上述 Update 函數的運作流程如下

Step 1. 檢查控制器 是否連接,如果控制器已經連接完成再進行 Step2。

Step2. 取出控制器的最新狀態。

Step3. 檢查控制器的按鈕狀態。

  1. 如果左類比搖桿的 X 數值大於 0 (也就是左邊的類比搖桿是朝右邊移動),則將圖片的X座標加 1。
  2. 如果左類比搖桿的 X 數值小於 0 (也就是左邊的類比搖桿是朝左邊移動),則將圖片的X座標減 1。
  3. 如果左類比搖桿的 Y 數值大於 0 (也就是左邊的類比搖桿是朝上邊移動),則將圖片的Y座標加 1。
  4. 如果左類比搖桿的 Y 數值小於 0 (也就是左邊的類比搖桿是朝下邊移動),則將圖片的Y座標減 1。

由於 Update 的函數是不斷的呼叫執行,所以 Step1 到 Step3 會不斷的進行檢查。

在 Draw 的函數當中,我們就來將畫面顯示出來,輸入以下的程式碼

spriteBatch.Begin();
    spriteBatch.Draw(pic, position, Color.White);
    spriteBatch.End();

當你按下 F5 編譯以後,你就可以將你的控制器拿起,操作圖片的移動。

 

[觀看教學文章]  [下載影片及範例資料]

 

【教學影片下載】

【範例程式碼下載】