设计以 XNA 为基础的 Windows Phone 7 游戏(转载)

junwong 发布于 2012/02/17 11:01
阅读 445
收藏 0

摘要

在上一篇文章中我们为大家介绍了 XNA Game Studio 4.0 的基本功能与支持游戏设计的特性和优势,做为使用 XNA Game Studio 4.0 版设计游戏程序的基础。这一回我们将要为大家介绍如何使用 Visual Studio 2010 或 Visual Studio 2010 Express for Windows Phone 设计以 XNA 为基础的 Windows Phone 7 游戏程序,并了解以 XNA 为基础的游戏程序的基础架构与核心功能。

XNA 游戏程序结构

使用 Microsoft Visual Studio 2010 Express for Windows Phone 建立的 Windows Phone Game (4.0) 型态的项目中,名称为 Game1.cs 的程序档案是整个游戏最主要的核心,负责定义名称为 Game1 的类别,打造以 XNA 为基础的游戏的基本结构。有关使用 Microsoft Visual Studio 2010 Express for Windows Phone 建立 XNA 游戏项目的说明可以参考:[Windows Phone 7 智能型手机应用程序开发总览]一文的说明。

Game1 类别继承自 XNA Framework 提供的 Microsoft.Xna.Framework.Game 类别,预设会覆写基础类别的 Initialize 方法、LoadContent 方法、UnloadContent 方法、Update 方法、Draw 方法,加上 Game1 类别自己的建构函式,形成游戏最基本的结构。例如以下就是一个 XNA 游戏类别的最基本的类别及类别的结构:

public class Game1 : Microsoft.Xna.Framework.Game

{

public Game1() {}

protected override void Initialize() {}

protected override void LoadContent() {}

protected override void UnloadContent() {}

protected override void Update(GameTime gameTime) {}

protected override void Draw(GameTime gameTime) {}

}

Game 类别主要方法的功能

在 Game1 类别覆写基础类别的方法中,名称为 Initialize 的方法与 Game1 类别的建构函式负责执行游戏初始化的工作,名称为 LoadContent 的方法负责自 Content Pipeline 项目加载透过 Content Pipeline 技术预先处理成二进制数据的游戏资源,名称为 UnloadContent 的方法负责执行释放资源的动作,请注意以 XNA 为基础的应用程序只需要释放非 ContentManager 管理的资源即可,意即未透过 ContentManager 类别的Add方法加入到 ContentManager 进行管理的资源才有需要在 UnloadContent 方法执行释放资源的动作。

Game1 类别中名称为 Update 的方法负责更新游戏的状态,例如要将游戏的主角从 X 坐标等于 100 的位置移动到 X 坐标为 500 的位置,改变主角坐标的动作就可以在 Update 方法中执行。请注意 Update 方法只负责更新游戏的状态,不负责更新游戏的显示画面,换句话说,Update 方法只负责更新主角的坐标位置,但是并不负责将主角显示在新的坐标位置,负责更新游戏显示内容的是名称为 Draw 的方法,所有显示游戏最新状态的工作,皆由 Draw 方法负责执行。

XNA 游戏程序的基本结构

了解 Game1 类别各个方法的基本功能之后,接下来我们就要来探讨 Game1 类别各个方法必须执行的工作,以成功地建立一个能够执行的 Windows Phone 7 游戏程序。

图1 所示即为一个 Windows Phone 7 游戏程序从启动到结束执行的运作过程,以及游戏程序执行过程中每个阶段必须执行的工作:

图1:Windows Phone 7 游戏程序从启动到结束执行的各个阶段必须执行的工作

[注意]

以 XNA 为基础的 Windows Phone 7 游戏程序在游戏一开始会自动建立游戏核心类别 (即 Game1 类别) 的对象,程序设计师不需要制作建立 Game1 类别的对象的程序代码。

游戏程序开始执行并完成建立 Game1 类别的对象之后,第二个阶段就是执行游戏初始化。游戏初始化阶段主要的工作在建立 GraphicsDeviceManager 类别的对象。假设当做游戏核心的类别的名称为 Game1,则我们可以在 Game1 类别的建构函式中执行建立 GraphicsDeviceManager 类别的对象的动作,并设定 GraphicsDeviceManager 类别的对象的 PreferredBackBufferHeight 属性和 PreferredBackBufferWidth 属性,指定游戏窗口的高度和宽度。除了设定 GraphicsDeviceManager 类别的对象的属性以外,我们还可以设定 Game1 类别的对象的 TargetElapsedTime 属性,控制游戏程序更新状态及显示内容的频率,做法如下:

public Game1()
{
    graphics = new GraphicsDeviceManager(this);//建立 GraphicsDeviceManager 類別的物件
    Content.RootDirectory = "Content";					//設定遊戲資源的根目錄
    graphics.PreferredBackBufferHeight = 480;				//設定遊戲視窗的高度
    graphics.PreferredBackBufferWidth = 800;				//設定遊戲視窗的寬度
    // Frame rate is 30 fps by default for Windows Phone.
    TargetElapsedTime = 
TimeSpan.FromTicks(333333);//設定遊戲程式更新狀態及顯示內容的頻率為每秒 30 次
}

[说明]

Windows Phone 7 智能型手机目前只有屏幕高度为 800,宽度为 480 的版本,因此将游戏窗口设定成高度 480,宽度 800 的大小,表示游戏要以横式屏幕的方式执行,另外 Game1 类别的对象的 TargetElapsedTime 属性负责控制游戏程序更新状态及显示内容的频率,将 TargetElapsedTime 属性设定成 333333,表示更新频率为 0.0333333,也就是每秒要更新 30 次。请注意每秒更新 30 次适合在 Windows Phone 7 智能型手机平台执行的游戏,但是不一定适合在 PC 个人计算机平台或 Xbox 360 游机

游戏程序完成初始化之后,第三个阶段负责执行加载游戏资源的动作,也就是要加载游戏程序执行的时候需要用到所有资源,包括音效、音乐、图形、和字型等等。负责加载游戏程序需要使用的所有资源的动作可以交给 Game1 类别的 LoadContent 方法负责完成,例如以下就是负责加载游戏程序需要使用的图形资源的程序代码:

Texture2D genie = null;								//宣告Texture2D類別的物件

protected override void LoadContent()
{
    // Create a new SpriteBatch, which can be used to draw textures.
    spriteBatch = new SpriteBatch(GraphicsDevice);		//建立 SpriteBatch 類別的物件

    // TODO: use this.Content to load your game content here
    genie = Content.Load<Texture2D>("genie");
}

请注意上述的程序代码会在游戏程序初始化的阶段建立 SpriteBatch 类别的对象,而建立 SpriteBatch 类别的对象的时候需要传入 GraphicsDeviceManager 类别的对象当做参数。SpriteBatch 类别的对象主要的用途在显示游戏程序欲显示的 2D 图形,包括游戏背景、游戏人物、游戏的状态、甚至是游戏提示供用户选取的菜单。

除了建立 SpriteBatch 类别的对象以外,游戏程序必须在初始化的阶段负责加载游戏程序执行时需要用到的所有资源,例如上述的程序代码中这一行程序代码:

genie = Content.Load<Texture2D>("genie");

负责从 Content Pipeline 项目的根目录加载名称为 genie 的资源,因为程序代码指定欲加载的是 Texture2D 格式的资源,也就是图形资源,所以在 Content Pipeline 项目中必须备妥名称为 genie 的图形档案,其扩展名可以是 .bmp、.dds、.dib、.hdr、.jpg、.pfm、.png、.ppm、和 .tga 等常见的图形格式档案。有关 XNA 游戏程序支持的图形文件格式可以参考 认识 XNA Game Studio 4.0 一文的说明。

[提示]

将上述程序代码中的 Texture2D 型态更换成 SoundEffect 型态,可以自 Content Pipeline 项目加载声音文件 (扩展名为 .wma 的档案),将上述程序代码中的 Texture2D 型态更换成 Song 型态,可以自 Content Pipeline 项目加载音乐档案 (扩展名为 .mp3 的档案),而将上述程序代码中的 Texture2D 型态更换成 SpriteFont 型态,可以自 Content Pipeline 项目加载字型定义档案 (扩展名为 .SpriteFont 的档案)。

[说明]

请注意上述的程序先在类别中宣告了一个型态为 Texture2D 类别,名称为 genie 的变量,负责管理游戏程序需要使用的图形。

加载妥游戏执行时需要用到的所有资源之后,游戏程序就可以进入运行时间,处理使用者的输入,更新游戏的状态,并显示游戏最新的内容。XNA 游戏程序一进入运行时间便会不断地呼叫 Update 方法和 Draw 方法,其详细的行为与呼叫的频率稍后会有详细的讨论。

假设游戏程序利用 Game1 类别定义的 pos 变量控制游戏人物显示的位置,则程序设计师可以于 Game1 类别的 Update 方法中更新 pos 变量的内容值,以便改变游戏人物显示的位置,完成更新游戏状态的工作,如下:

int pos = 0;										//存放遊戲人物位置的變數

protected override void Update(GameTime gameTime)
{
    // Allows the game to exit
    if (GamePad.GetState(PlayerIndex.One).Buttons.Back ==
ButtonState.Pressed)	 //如果使用者按下智慧型手機的 [Back] 鍵,回到上一個畫面
        this.Exit();										//結束遊戲程式
if (pos <= 500)							//如果 pos 變數的內容值不大於 500
    {
        pos++;										//遞增 pos 變數的內容值
    }
    base.Update(gameTime);						//呼叫基礎類別的 Update 方法
}

请注意 Game1 类别的 Update 方法只负责更新游戏的状态,不负责更新游戏显示的内容,更新游戏显示内容的工作是由 Game1 类别的 Draw 方法负责的。例如以下的 Draw 方法便会将游戏的人物移至 X 坐标等于 pos 变量的内容值的位置:

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.CornflowerBlue);		//清除遊戲程式目前顯示的內容

    // TODO: Add your drawing code here
    spriteBatch.Begin();							//宣告顯示遊戲內容的動作開始
    spriteBatch.Draw(genie, new Vector2(pos,100),
Color.White);//將 genie 變數所管理的圖形的 x 座標顯示在 pos 變數的內容值指定的位置
    spriteBatch.End();							//宣告顯示遊戲內容的動作結束
    base.Draw(gameTime);								//呼叫基礎類別的 Draw 方法
}

[提示]

以 XNA 为基础的游戏程序可以在呼叫 spriteBatch 对象的 Begin 方法和呼叫 spriteBatch 对象的 End 方法之间执行多个绘制图形和文字的动作,由 XNA Framework 以批次的方式一次显示多个图形内容。另外还有一点需要提醒大家的是 Game1 类别的 Update 方法和 Draw 方法都会接一个型态为 GameTime 的参数,程序设计师可以从这个参数得知游戏程序开始迄今的时间,以及自上一次 Update 方法被呼到迄今的时间,做为控制更新游戏状态与更新游戏内容的参考。

当游戏程序结束执行的时候,游戏程序可以利用 Game1 类别的 UnloadContent 方法释放所有未透过呼叫 Content 对象的 Load 方法加载的资源。换句话说,所有透过呼叫 Content 对象的 Load 方法加载的资源可以不需要执行释放的动作,呼叫 Content 对象的 Load 方法加载的资源会由 ContentManager 负责执行释放的动作。

游戏程序执行的最后一个阶段是结束执行,结束游戏程序执行的动作很简单,游戏程序只要呼叫 Game1 类别的 Exit 方法就可以结束游戏程序的执行。

Update 方法与 Draw 方法的呼叫时机

前面有提到,XNA 游戏程序一进入运行时间便会不断地呼叫 Update 方法和 Draw 方法,其中的 Update 方法负责更新游戏程序的状态,而 Draw 方法则负责显示游戏的内容。请注意并不是每一次 Update 方法被呼叫之后,Draw 方法就会跟着被呼叫,Update 方法与 Draw 方法被呼叫的频率要视 Game1 类别的 IsFixedTimeStep 属性的内容值而定。

如果 Game1 类别的 IsFixedTimeStep 属性的内容值为 true (默认值),则游戏程序处于固定更新 (fixed-step) 模式。使用固定更新模式的游戏程序,其 Update 方法被呼叫的频率是由 Game1 类别的 TargetElapsedTime 属性的内容值定义的,其默认值视执行游戏程序的平台的不同而有不同。如果游戏程序在 PC 个人计算机或 Xbox 360 游戏机中执行,Update 方法呼叫的频率为每秒 60 次,如果游戏程序在 Windows Phone 7 智能型手机中执行,因为其处理器的速度较慢,Update 方法呼叫的频率为每秒 30 次。

请注意 Update 方法被呼叫的频率是一个游戏程序努力要达到的目标值,而不是一定可以达到的数据。如果游戏程序在 PC 个人计算机或 Xbox 360 游戏机上执行,但是却无法在 1/60 秒内完成 Update 方法和 Draw 方法执行的工作,则 Update 方法的 gameTime 参数 (型态为 GameTime 类别) 的 IsRunningSlowly 属性将会被设定为 true,表示游戏程序无法以正常的速度执行,此时游戏程序会在呼叫 Update 方法之后,将不会伴随着呼叫负责显示游戏内容的 Draw 方法,而是继续呼叫 Update 方法,以跟上 TargetElapsedTime 属性的内容值定义的更新频率,如果此举还是无法令游戏程序跟上欲达到的更新频率,则放弃。其结果将会造成游戏程序在呼叫负责更新游戏状态的 Update 方法几次之后才呼叫一次负责显示内容的 Draw 方法,因此游戏显示的人物的动作将会呈现动作不顺畅的现象。

当游戏程序出现动作更新显示不顺畅的现象时,我们可以降低 TargetElapsedTime 属性内容值,降低应用程序的更新频率,或是将 Game1 类别的 IsFixedTimeStep 属性的内容值为 false,令游戏程序以可变更新 (variable-step) 模式来执行。请注意以可变更新模式执行的游戏程序会不断地呼叫 Update 方法和 Draw 方法,周而复始而且不间断,不管 Game1 类别的 TargetElapsedTime 属性的设定值为何。

[特别注意]

不管以 XNA 为基础的游戏程序采用固定更新 (fixed-step) 模式执行,或是采用可变更新 (variable-step) 模式执行,Game1 类别的 Update 方法和 Draw 方法都会持续地被呼叫,直到游戏结束为止,也就是说游戏程序本身都已经身处循环之中,除非有特殊的需求,否则在 Update 方法和 Draw 方法中不需要再使用循环的语法进行控制。例如我们要将游戏中的动画人物从X坐标为 0 的位置移动到 X 坐标为 500 的位置,不可以在 Game1 类别的 Update 方法加入以下的程序代码,以更新动画人物的显示位置 (假设 pos 是负责控制动画人物 X 坐标位置的变量):

for (int i = 0; i <= 500; i++)
{
    pos = i;
}

因为上述的循环在执行的时候会造成 Update 方法执行较久,等 Update 方法执行完毕才会呼叫 Draw 方法,所以游戏程序执行的时候我们将会看到动画人物原本在X坐标为 0 的位置,等循环跑完,动画人物会直接在X坐标为 500 的位置出现,用户将不会看到动画人物从X坐标为 0 的位置移至 X 坐标为 500 的位置的移动过程,造成动画人物移动的过程很突兀,没有渐进的效果。

要令动画人物移动位置的时候有渐进的效果,我们可以在 Update 方法中利用以下的程序代码改变负责控制动画人物 X 坐标位置的 pos 变量的内容值:

if (pos <= 500)
{
    pos++;
}

因为 Update 方法会被持续不断地呼叫,每被呼叫一次,动画人物的 X 坐标的内容值就会改变,当 Draw 方法被呼叫的时候,使用者就可以看到动画人物渐进移动至目标位置的效果。

[结语]

这一回我们为大家介绍了如何使用 Visual Studio 2010 或 Visual Studio 2010 Express for Windows Phone 设计以 XNA 为基础的 Windows Phone 7 游戏程序,并了解以 XNA 为基础的游戏程序的基础架构与核心功能。下一回我们将要为大家介绍 XNA Framework 支持游戏程序制作的重要类别,做为开发游戏程序的基础知识。

原文链接: http://msdn.microsoft.com/zh-cn/windowsphone/gg415615.aspx

加载中
返回顶部
顶部