摘要:
我們知道在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),原來的代碼如下:
- 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.Input.Touch;
- using Microsoft.Xna.Framework.Media;
- namespace WindowsPhoneGameDemo
- {
- public class Game1 : Microsoft.Xna.Framework.Game
- {
- GraphicsDeviceManager graphics;
- SpriteBatch spriteBatch;
- Dictionary<int, Texture2D> dicImgs = new Dictionary<int, Texture2D>();
- Texture2D currentImg = null;
- int index = 1;
- public Game1()
- {
- graphics = new GraphicsDeviceManager(this);
- Content.RootDirectory = "Content";
- TargetElapsedTime = TimeSpan.FromTicks(333333);//此處可修改全局幀頻
- }
- protected override void Initialize()
- {
- base.Initialize();
- currentImg = dicImgs[1];//設置默認值
- }
- protected override void LoadContent()
- {
- spriteBatch = new SpriteBatch(GraphicsDevice);
- for (int i = 1; i <= 4; ++i)
- {
- dicImgs.Add(i, this.Content.Load<Texture2D>(i.ToString()));
- }
- }
- protected override void UnloadContent()
- {
- }
- protected override void Update(GameTime gameTime)
- {
- if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
- this.Exit();
- if (index > 4)
- {
- index = 1;
- }
- currentImg = dicImgs[index];
- index++;
- base.Update(gameTime);
- }
- protected override void Draw(GameTime gameTime)
- {
- GraphicsDevice.Clear(Color.CornflowerBlue);
- spriteBatch.Begin();
- spriteBatch.Draw(currentImg,new Vector2(320,135), Color.White);
- spriteBatch.End();
- 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.Input.Touch;
- using Microsoft.Xna.Framework.Media;
- namespace WindowsPhoneGameDemo
- {
- public class Game1 : Microsoft.Xna.Framework.Game
- {
- GraphicsDeviceManager graphics;
- SpriteBatch spriteBatch;
- Dictionary<int, Texture2D> dicImgs = new Dictionary<int, Texture2D>();
- Texture2D currentImg = null;
- int index = 1;
- int timeSinceLastFrame = 0;//記錄更新間隔
- int millisecondsPerFrame = 330;//設置時間間隔
- public Game1()
- {
- graphics = new GraphicsDeviceManager(this);
- Content.RootDirectory = "Content";
- TargetElapsedTime = TimeSpan.FromTicks(333333);//此處可修改全局幀頻
- }
- protected override void Initialize()
- {
- base.Initialize();
- currentImg = dicImgs[1];//設置默認值
- }
- protected override void LoadContent()
- {
- spriteBatch = new SpriteBatch(GraphicsDevice);
- for (int i = 1; i <= 4; ++i)
- {
- dicImgs.Add(i, this.Content.Load<Texture2D>(i.ToString()));
- }
- }
- protected override void UnloadContent()
- {
- }
- protected override void Update(GameTime gameTime)
- {
- if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
- this.Exit();
- timeSinceLastFrame += gameTime.ElapsedGameTime.Milliseconds;
- if (millisecondsPerFrame <= timeSinceLastFrame)//只有小於等於指定的時間間隔才進行圖片切換
- {
- timeSinceLastFrame -= millisecondsPerFrame;
- if (index > 4)
- {
- index = 1;
- }
- currentImg = dicImgs[index];
- index++;
- }
- base.Update(gameTime);
- }
- protected override void Draw(GameTime gameTime)
- {
- GraphicsDevice.Clear(Color.CornflowerBlue);
- spriteBatch.Begin();
- spriteBatch.Draw(currentImg,new Vector2(320,135), Color.White);
- spriteBatch.End();
- base.Draw(gameTime);
- }
- }
- }
下面我們對比一下這個動畫的修改前後的效果: