XNA4.0學習筆記2:控制精靈和碰撞檢測

來源:互聯網
上載者:User

                                           精靈的控制和碰撞檢測


        上一節我們瞭解了精靈的繪製,移動以及動畫的實現,並且在最後我們實現了三個環的簡單動畫,今天我們學習下如何通過裝置控制精靈,這一節的內容比較簡單,很好理解,在這裡我先把控制精靈的全部代碼貼上來,方便接下來的學習!

using System;using System.Collections.Generic;using System.Linq;using Microsoft.Xna.Framework;using Microsoft.Xna.Framework.Audio;using Microsoft.Xna.Framework.Content;using Microsoft.Xna.Framework.GamerServices;using Microsoft.Xna.Framework.Graphics;using Microsoft.Xna.Framework.Input;using Microsoft.Xna.Framework.Media;namespace WindowsGame6{       public class Game1 : Microsoft.Xna.Framework.Game    {        GraphicsDeviceManager graphics;        SpriteBatch spriteBatch;        Texture2D ringtexture;                                         //三環動畫的相關變數        Point ringframeSize = new Point(75, 75);        Point ringcurrentFrame = new Point(0, 0);                        Point ringsheetSize = new Point(6, 8);        Vector2 ringpos1 = Vector2.Zero;        const float ringspeed = 5;        Texture2D skulltexture;                                        //骷髏頭動畫相關變數        Point skullframeSize = new Point(75, 75);        Point skullcurrentFrame = new Point(0, 0);        Point skullsheetSize = new Point(6, 8);        MouseState prevmousestate;        public Game1()        {            graphics = new GraphicsDeviceManager(this);            Content.RootDirectory = "Content";        }        protected override void Initialize()        {            // TODO: 在此處添加初始化邏輯            base.Initialize();        }        protected override void LoadContent()        {            // 建立新的 SpriteBatch,可將其用於繪製紋理。            spriteBatch = new SpriteBatch(GraphicsDevice);            ringtexture = Content.Load<Texture2D>("Images//threerings");         //載入兩幅位元影像            skulltexture = Content.Load<Texture2D>("Images//skullball");            // TODO: 在此處使用 this.Content 載入遊戲內容        }        protected override void UnloadContent()        {            // TODO: 在此處取消載入任何非 ContentManager 內容        }        protected override void Update(GameTime gameTime)        {            // 允許遊戲退出            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)                this.Exit();                        ++ringcurrentFrame.X;                                               //迴圈三環精靈位元影像            if (ringcurrentFrame.X >= ringsheetSize.X)            {                ringcurrentFrame.X = 0;                ++ringcurrentFrame.Y;                if (ringcurrentFrame.Y >= ringsheetSize.Y)                    ringcurrentFrame.Y = 0;            }            ++skullcurrentFrame.X;                                               //迴圈骷髏精靈位元影像            if (skullcurrentFrame.X >= skullsheetSize.X)            {                skullcurrentFrame.X = 0;                ++skullcurrentFrame.Y;                if (skullcurrentFrame.Y >= skullsheetSize.Y)                    skullcurrentFrame.Y = 0;            }            // TODO: 在此處添加更新邏輯            KeyboardState keyboardstate = Keyboard.GetState();                     //鍵盤控制三環動畫語句            if (keyboardstate.IsKeyDown(Keys.Left))                ringpos1.X -= ringspeed;            if (keyboardstate.IsKeyDown(Keys.Right))                ringpos1.X += ringspeed;            if (keyboardstate.IsKeyDown(Keys.Up))                ringpos1.Y -= ringspeed;            if (keyboardstate.IsKeyDown(Keys.Down))                ringpos1.Y += ringspeed;            MouseState mouseState = Mouse.GetState();                               //滑鼠控制三環動畫語句            if (mouseState.X != prevmousestate.X || mouseState.Y != prevmousestate.Y)                 ringpos1 = new Vector2(mouseState.X, mouseState.Y);             prevmousestate = mouseState;            if (ringpos1.Y < 0)                                                     //使三環精靈一直保持在視窗中                ringpos1.Y = 0;            if (ringpos1.Y > Window.ClientBounds.Height - ringframeSize.Y)                ringpos1.Y = Window.ClientBounds.Height - ringframeSize.Y;            if (ringpos1.X < 0)                ringpos1.X = 0;            if (ringpos1.X > Window.ClientBounds.Width - ringframeSize.X)                ringpos1.X = Window.ClientBounds.Width - ringframeSize.X;            base.Update(gameTime);        }        protected override void Draw(GameTime gameTime)        {            GraphicsDevice.Clear(Color.CornflowerBlue);            spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.AlphaBlend);             spriteBatch.Draw(                                                         //繪製三環精靈                ringtexture,ringpos1,                                     new Rectangle(ringcurrentFrame.X * ringframeSize.X,                ringcurrentFrame.Y * ringframeSize.Y,                ringframeSize.X, ringframeSize.Y),                Color.White,                0,                Vector2.Zero,                1,                SpriteEffects.None,                0);            spriteBatch.Draw(                                                         //繪製骷髏精靈               skulltexture, new Vector2(100,100),               new Rectangle(skullcurrentFrame.X * skullframeSize.X,               skullcurrentFrame.Y * skullframeSize.Y,               skullframeSize.X, skullframeSize.Y),               Color.White,               0,               Vector2.Zero,               1,               SpriteEffects.None,               0);            spriteBatch.End();            // TODO: 在此處添加繪圖代碼            base.Draw(gameTime);        }    }}

1:更多精靈的繪製

在昨天那個三環精靈程式碼的基礎上,現在我們需要再多加一個精靈位元影像進來,還是老辦法:

這是一副骷髏精靈位元影像,跟三環動畫一樣在類最前面加上那幾行代碼,並且在loadcontent函數中載入位元影像,並且在draw函數中繪製出位元影像,為了不與第一幅重複,我們這裡設定繪製的座標為(100,100),然後運行,可以看到螢幕中有兩個動畫在旋轉!

2:使用鍵盤控制精靈的移動!

這裡需要一點新知識了,鍵盤輸入是通過Microsoft.XNA.Framework.Input命名空間中的Keyboard類來處 理的。Keyboard 類有一個叫做 GetState 的靜態方法,用 KeyboardState 結構的形式返 回鍵盤目前的狀態。

KeyboardState 結構中包含三個能夠滿足您大部分的功能需求的關鍵方法如下:

Keys[] GetPressedKeys() 返回一個在方法被調用時被按下的鍵的數組 

bool IsKeyDown(Keys key) 返回 true 或 false,取決於方法調用時參數所代表的 按鍵是否被按下 

bool IsKeyUp(Keys key) 返回 true 或 false,取決於方法調用時參數所代表的 按鍵是否被釋放 

舉個例子,如果要檢測鍵盤的A鍵是否被按下,則該這樣來寫代碼:

if(Keyboard.GetState( ).IsKeyDown(Keys.A));

好了,現在我們可以來著手實現鍵盤的上下左右控制三環動畫的移動了,這裡跟昨天一樣,需要加一個Vector2的變數ringpos1,並且在draw的方法中改變三環動畫的位置為ringpos1,

接下來就應該在update方法中實現移動的距離更新,代碼如下:

KeyboardState keyboardstate = Keyboard.GetState();                     //鍵盤控制三環動畫語句            if (keyboardstate.IsKeyDown(Keys.Left))                ringpos1.X -= ringspeed;            if (keyboardstate.IsKeyDown(Keys.Right))                ringpos1.X += ringspeed;            if (keyboardstate.IsKeyDown(Keys.Up))                ringpos1.Y -= ringspeed;            if (keyboardstate.IsKeyDown(Keys.Down))                ringpos1.Y += ringspeed;

這裡就如同上面貼出來的一樣,我們之所以不用if else,而是用4個if是因為這樣可以同時從兩個方向移動,比如上左,右下,如果改為if else就只能向其中一個方向移動,現在可以編譯運行,使用鍵盤的上下左右,就可以移動我們的三環動畫了!!

3:使用滑鼠控制三環動畫!

XNA 提供了一個和 Keyboard 類行為很相似的 Mouse 類來和滑鼠進行互動。Mouse 類也 有一個 GetState 方法,能以 MouseState 結構的形式從滑鼠返回資料。

MouseState               有一些屬 性將會協助您瞭解到當您調用 GetState 時滑鼠在特定時刻發生了什麼。具體如下:

LeftButton ButtonState               返回滑鼠左鍵的狀態

 MiddleButton ButtonState              返回滑鼠中鍵的狀態

 RightButton ButtonState            返 回滑鼠右鍵的狀態 

ScrollWheelValue int                返回自遊戲開始後滑鼠滾輪滾動刻度的累加量.要想知 道滾輪滾動了多少,把當前幀的ScrollWheelValue和 上一幀的進行比較. 

X int                   返回滑鼠游標相對於遊戲視窗左上方的水平位置(坐 標).如果滑鼠游標在遊戲視窗的左側,這個值是負值;如 果在遊戲視窗右邊,這個值大於遊戲視窗的寬度

. XButton1 ButtonState               返回某些滑鼠上額外的按鍵的狀態 

XButton2 ButtonState                返回某些滑鼠上額外的按鍵的狀態 

Y int               返回滑鼠游標相對於遊戲視窗左上方的垂直位置(坐 標).如果滑鼠游標在遊戲視窗的上方,這個 值是負值; 如果在遊戲視窗下方,這個值大於遊戲視窗的高度.

為了確定滑鼠是否被移動,在 Game1 類頂部添加一個類成員變數:  

MouseState  preMouseState; (如所示)

將以下代碼添加到 Update 方法中,位於 base.Update 方法的調用之前:

MouseState mouseState = Mouse.GetState();                               //滑鼠控制三環動畫語句            if (mouseState.X != prevmousestate.X || mouseState.Y != prevmousestate.Y)                 ringpos1 = new Vector2(mouseState.X, mouseState.Y);             prevmousestate = mouseState;

現在編譯運行,則三環動畫會跟著滑鼠走,我們的滑鼠控制也就完成了!

4:使動畫保留在視窗之間

您可能已經注意到了,三環精靈會在您將它移動得足夠遠時消失在螢幕的邊緣。讓玩家控 制的物體能夠離開螢幕並且消失不見永遠不會是一個好主意。要糾正這個問題,您需要在 Update 函數的結尾更新精靈的位置。如果精靈已經向左、向右、向上或向下移動得太遠,更 正它的位置來使其保持在遊戲視窗中。將下面的代碼添加到 Update 方法的末尾,位於 base.Update 方法的調用之前: 

if (ringpos1.Y < 0)                                                     //使三環精靈一直保持在視窗中                ringpos1.Y = 0;            if (ringpos1.Y > Window.ClientBounds.Height - ringframeSize.Y)                ringpos1.Y = Window.ClientBounds.Height - ringframeSize.Y;            if (ringpos1.X < 0)                ringpos1.X = 0;            if (ringpos1.X > Window.ClientBounds.Width - ringframeSize.X)                ringpos1.X = Window.ClientBounds.Width - ringframeSize.X;

再次編譯運行,現在滑鼠和鍵盤都可以控制三環動畫的移動了,這時動畫始終是停留在視窗之內的!


5:一般性的碰撞檢測

大家知道碰撞檢測是遊戲中非常重要的一個環節,更是涉及到很多數學問題,可是在我們的XNA中,碰撞問題簡化得你都不敢想象,我們首先運行上面的哪一個程式:

這兩個精靈,骷髏頭暫時是固定的,我們可以用鍵盤控制三環精靈,實現碰見檢測可以利用矩形封裝法,也就是用兩個矩形封裝好精靈,然後檢查兩個矩形是否相交,則可判斷是否碰撞,效果如下:

接下來我們需要做的就是檢測兩個矩形在螢幕上是否相交,碰巧XNA為我們提供的矩形類裡面有這樣一個成員函數可以檢測矩形相交,新加一個成員函數,代碼如下:

protected bool colline()            //檢測碰撞的代碼        {            Rectangle ringRect = new Rectangle((int)ringpos1.X, (int)ringpos1.Y, ringframeSize.X, ringframeSize.Y);            Rectangle skullErct = new Rectangle((int)skullpos2.X, (int)skullpos2.Y, skullframeSize.X, skullframeSize.Y);            return ringRect.Intersects(skullErct);        }

在程式中建立了兩個矩形地區,構造方法中分別給予了兩個精靈的位置,傳回值為布爾類型,利用了矩形類的intersects方法,接下來可以在update方法中檢測碰撞了

if(colline() ).....則執行相關的事情,在這裡我們調用Exit函數,如果碰撞,就馬上終止程式(雖然這不符合邏輯,這裡只是為了示範).

關於碰撞檢測,需要對於矩形的大小和遊戲效率做出權衡,保證在使用者眼睛無法分辨的時候最佳,不可盲目追求碰撞精確性而做過多操作,只會犧牲遊戲效率這是不值得的,

由於本節內容很簡單,到此為止

下一期:使用者自訂精靈類!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.