[csharp]
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);
}
}
}
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方法中實現移動的距離更新,代碼如下:
[csharp]
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;
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 方法的調用之前:
[csharp]
MouseState mouseState = Mouse.GetState(); //鼠標控制三環動畫語句
if (mouseState.X != prevmousestate.X || mouseState.Y != prevmousestate.Y)
ringpos1 = new Vector2(mouseState.X, mouseState.Y);
prevmousestate = mouseState;
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 方法的調用之前:
[csharp]
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;
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為我們提供的矩形類裡面有這樣一個成員函數可以檢測矩形相交,新加一個成員函數,代碼如下:
[csharp]
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);
}
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函數,如果碰撞,就馬上終止程序(雖然這不符合邏輯,這裡只是為了演示).
關於碰撞檢測,需要對於矩形的大小和游戲效率做出權衡,保證在用戶眼睛無法分辨的時候最佳,不可盲目追求碰撞精確性而做過多操作,只會犧牲游戲效率這是不值得的,
由於本節內容很簡單,到此為止