XNA遊戲開發之速度調整

摘要:

我們知道在Windows Phone 7中XNA遊戲默認的幀頻是30fps(PC和xbox360中是60fps),可是實際遊戲開發過程中這個值未必都能滿足我們的需求。下面我們就一塊看一下在XNA遊戲開發過程中如何調整遊戲的速度。

內容:

在Game類中有一個屬性TargetElapsedTime,用來表示每一幀之間的時間間隔,例如默認爲1/30秒,也就是幀頻爲30fps。如果仔細看一下你會發現在VS自動生成的Game1類的構造函數中給TargetElapsedTime屬性賦值爲TimeSpan .FromTicks(333333) ,也就是時間間隔爲 0.0333… 秒,幀頻 30fps 。既然如此我們就可以修改這個值達到我們想要的結果,例如我們修改爲 333333*2 就可以將速度放慢一倍(當然也可以不使用刻度爲單位,例如使用 TimeSpan .FromSeconds(1/15) )。

這種方法看似可行,但是多數情況下我們沒有辦法這麼做,因爲如果修改了 TargetElapsedTime屬性就表示整個遊戲的幀頻都進行了修改。通常遊戲中不可能都是某種固定幀頻,一般都是遊戲中有些元素運動得快,有些元素運動的慢,因此很難用某種統一的速度來設置。這個時候我們怎麼辦呢?

我們知道遊戲的動畫速度取決於Update中動態變量變化的程度,如果我們可以控制變量的變化速度就可以修改遊戲的速度。此時我們注意到Update方法有一個GameTime類型的參數,它有一個屬性ElapsedGameTime ,表示從上一幀到這一幀的時間間隔。有了它我們只需要設置一個變量用來記錄時間間隔,只有間隔到達我們需要的值時纔在Update中修改動態變量,這樣的話就可以變形的修改動畫速度了。例如下面一個通過動態更改圖片來形成動畫效果Demo(圖片在對應的Content中,分別爲1.png、2.png、3.png、4.png、5.png),原來的代碼如下:

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using Microsoft.Xna.Framework;  
  5. using Microsoft.Xna.Framework.Audio;  
  6. using Microsoft.Xna.Framework.Content;  
  7. using Microsoft.Xna.Framework.GamerServices;  
  8. using Microsoft.Xna.Framework.Graphics;  
  9. using Microsoft.Xna.Framework.Input;  
  10. using Microsoft.Xna.Framework.Input.Touch;  
  11. using Microsoft.Xna.Framework.Media;  
  12. namespace WindowsPhoneGameDemo  
  13. {  
  14.     public class Game1 : Microsoft.Xna.Framework.Game  
  15.     {  
  16.         GraphicsDeviceManager graphics;  
  17.         SpriteBatch spriteBatch;  
  18.         Dictionary<int, Texture2D> dicImgs = new Dictionary<int, Texture2D>();  
  19.         Texture2D currentImg = null;  
  20.         int index = 1;  
  21.         public Game1()  
  22.         {  
  23.             graphics = new GraphicsDeviceManager(this);  
  24.             Content.RootDirectory = "Content";  
  25.             TargetElapsedTime = TimeSpan.FromTicks(333333);//此處可修改全局幀頻  
  26.               
  27.         }  
  28.         protected override void Initialize()  
  29.         {  
  30.             base.Initialize();  
  31.             currentImg = dicImgs[1];//設置默認值  
  32.         }  
  33.         protected override void LoadContent()  
  34.         {  
  35.             spriteBatch = new SpriteBatch(GraphicsDevice);  
  36.             for (int i = 1; i <= 4; ++i)  
  37.             {  
  38.                 dicImgs.Add(i, this.Content.Load<Texture2D>(i.ToString()));  
  39.             }  
  40.         }  
  41.         protected override void UnloadContent()  
  42.         {  
  43.         }  
  44.         protected override void Update(GameTime gameTime)  
  45.         {  
  46.             if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)  
  47.                 this.Exit();  
  48.             if (index > 4)  
  49.             {  
  50.                 index = 1;  
  51.             }  
  52.             currentImg = dicImgs[index];  
  53.             index++;  
  54.             base.Update(gameTime);  
  55.         }  
  56.         protected override void Draw(GameTime gameTime)  
  57.         {  
  58.             GraphicsDevice.Clear(Color.CornflowerBlue);  
  59.             spriteBatch.Begin();  
  60.             spriteBatch.Draw(currentImg,new Vector2(320,135), Color.White);  
  61.             spriteBatch.End();  
  62.             base.Draw(gameTime);  
  63.         }  
  64.     }  
  65. }  

經過修改後:

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using Microsoft.Xna.Framework;  
  5. using Microsoft.Xna.Framework.Audio;  
  6. using Microsoft.Xna.Framework.Content;  
  7. using Microsoft.Xna.Framework.GamerServices;  
  8. using Microsoft.Xna.Framework.Graphics;  
  9. using Microsoft.Xna.Framework.Input;  
  10. using Microsoft.Xna.Framework.Input.Touch;  
  11. using Microsoft.Xna.Framework.Media;  
  12. namespace WindowsPhoneGameDemo  
  13. {  
  14.     public class Game1 : Microsoft.Xna.Framework.Game  
  15.     {  
  16.         GraphicsDeviceManager graphics;  
  17.         SpriteBatch spriteBatch;  
  18.         Dictionary<int, Texture2D> dicImgs = new Dictionary<int, Texture2D>();  
  19.         Texture2D currentImg = null;  
  20.         int index = 1;  
  21.         int timeSinceLastFrame = 0;//記錄更新間隔  
  22.         int millisecondsPerFrame = 330;//設置時間間隔  
  23.         public Game1()  
  24.         {  
  25.             graphics = new GraphicsDeviceManager(this);  
  26.             Content.RootDirectory = "Content";  
  27.             TargetElapsedTime = TimeSpan.FromTicks(333333);//此處可修改全局幀頻  
  28.               
  29.         }  
  30.         protected override void Initialize()  
  31.         {  
  32.             base.Initialize();  
  33.             currentImg = dicImgs[1];//設置默認值  
  34.         }  
  35.         protected override void LoadContent()  
  36.         {  
  37.             spriteBatch = new SpriteBatch(GraphicsDevice);  
  38.             for (int i = 1; i <= 4; ++i)  
  39.             {  
  40.                 dicImgs.Add(i, this.Content.Load<Texture2D>(i.ToString()));  
  41.             }  
  42.         }  
  43.         protected override void UnloadContent()  
  44.         {  
  45.         }  
  46.         protected override void Update(GameTime gameTime)  
  47.         {  
  48.             if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)  
  49.                 this.Exit();  
  50.             timeSinceLastFrame += gameTime.ElapsedGameTime.Milliseconds;  
  51.             if (millisecondsPerFrame <= timeSinceLastFrame)//只有小於等於指定的時間間隔才進行圖片切換  
  52.             {  
  53.                 timeSinceLastFrame -= millisecondsPerFrame;  
  54.                 if (index > 4)  
  55.                 {  
  56.                     index = 1;  
  57.                 }  
  58.                 currentImg = dicImgs[index];  
  59.                 index++;  
  60.             }  
  61.             base.Update(gameTime);  
  62.         }  
  63.         protected override void Draw(GameTime gameTime)  
  64.         {  
  65.             GraphicsDevice.Clear(Color.CornflowerBlue);  
  66.             spriteBatch.Begin();  
  67.             spriteBatch.Draw(currentImg,new Vector2(320,135), Color.White);  
  68.             spriteBatch.End();  
  69.             base.Draw(gameTime);  
  70.         }  
  71.     }  
  72. }  

下面我們對比一下這個動畫的修改前後的效果:

修改幀頻前

修改幀頻後

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章