windowsphone开发xna framew常用类.docx
《windowsphone开发xna framew常用类.docx》由会员分享,可在线阅读,更多相关《windowsphone开发xna framew常用类.docx(19页珍藏版)》请在冰豆网上搜索。
![windowsphone开发xna framew常用类.docx](https://file1.bdocx.com/fileroot1/2023-2/2/0106b0a8-7ad3-4072-a2ed-2a6eea4e84aa/0106b0a8-7ad3-4072-a2ed-2a6eea4e84aa1.gif)
windowsphone开发xnaframew常用类
上一回我们为大家介绍了如何使用VisualStudio2010或VisualStudio2010ExpressforWindowsPhone设计以XNA为基础的WindowsPhone7游戏程序,并了解以XNA为基础的游戏程序的基础架构与核心功能。
这一回我们将要为大家介绍XNAFramework支持游戏程序制作的重要类别,做为开发游戏程序的基础知识。
除此之外,我们也将利用本文所介绍的类别实作一个简单的游戏程序,并令其具有能够不断卷动的背景图案。
GraphicsDeviceManager类别
第一个要介绍给大家认识的是负责管理绘图装置的GraphicsDeviceManager类别。
以XNA为基础的游戏程序必须在初始化的时候建立妥GraphicsDeviceManager类别的对象,并设定包括游戏程序窗口高度与宽度在内的必要属性,做为显示游戏内容的基础。
有关于游戏程序初始化阶段建立GraphicsDeviceManager类别的对象的详细做法可以参考[设计以XNA为基础的WindowsPhone7游戏]一文的说明。
表1所示即为GraphicsDeviceManager类别常用的属性:
表1:
GraphicsDeviceManager类别常用的属性
属性名称
说明
IsFullScreen
控制游戏程序的窗口是否要以全屏幕的方式显示
PreferredBackBufferFormat
屏幕缓冲区的格式
PreferredBackBufferHeight
屏幕缓冲区的高度
PreferredBackBufferWidth
屏幕缓冲区的宽度
GraphicsDeviceManager类别常用的方法请参考表2的说明:
表2:
GraphicsDeviceManager类别常用的方法
方法名称
说明
ToggleFullScreen
在窗口模式和全屏幕模式中切换
游戏核心类别
以XNA为基础的游戏程序的主体是Game类别,也是做为游戏程序主体的Game1类别的基础类别。
游戏程序可以利用Game1类别的Update方法更新游戏的状态,利用Draw方法显示游戏的内容。
表3所示即为Game类别的常用属性:
表3:
Game类别常用的属性
属性名称
说明
Components
管理所有GameComponent的集合
Content
取得ContentManager对象的属性
GraphicsDevice
取得图型装置对象的属性
IsActive
判断游戏程序的窗口目前是否在作用中
IsFixedTimeStep
控制游戏程序要使用固定更新模式或是可变更新模式
TargetElapsedTime
当IsFixedTimeStep属性的内容值为true时,控制Update方法被呼叫的频率的属性
Game类别常用的方法可以参考表4的说明:
表4:
Game类别常用的方法
方法名称
说明
Exit
结束游戏程序的执行
BeginDraw
宣告绘制图形的动作开始
EndDraw
宣告绘制图形的动作结束
Draw
执行绘制游戏内容的动作
LoadContent
执行加载游戏资源的方法
UnloadContent
执行释放游戏资源的方法
Update
负责更新游戏状态的方法
如果程序设计师要以模块化的方式设计游戏程序,可以将游戏的人物制作成GameComponent类别或是DrawableGameComponent类别,再将GameComponent类别的对象或是DrawableGameComponent类别的对象加入到Game类别的对象的Conponents集合中,由Game类别的对象统一管理,把复杂的游戏人物的初始化、状态更新、以及更新显示等动作封装在GameComponent类别或是DrawableGameComponent类别中,可以有效简化Game类别的控制逻辑。
当游戏人物众多,角色复杂时,适当地利用GameComponent类别或是DrawableGameComponent类别可以提升游戏的可维护性,利于发展功能进阶,效果复杂的游戏。
XNAFramework提供的GameComponent类别和DrawableGameComponent类别的差别在于DrawableGameComponent类别管理的是有用户接口的游戏组件,而GameComponent类别所管理的则是没有用户接口的游戏组件。
换句话说,DrawableGameComponent类别提供了GameComponent类别未支持的LoadContent方法和Draw方法,以便执行加载所管理的游戏资源和显示游戏的内容的工作。
当建立好GameComponent类别的对象或DrawableGameComponent类别的对象之后,只要将GameComponent类别的对象或DrawableGameComponent类别的对象加入到Game类别的对象的Components集合中,GameComponent类别的对象或DrawableGameComponent类别的对象的Update方法就会被持续地呼叫,而DrawableGameComponent类别的对象的Draw方法也会在适当的时机被呼叫,并将游戏的内容显示到窗口中供用户操作。
欲为游戏程序项目加入GameComponent类别或DrawableGameComponent类别,可以使用鼠标的右键点中[SolutionExplorer]窗口中的项目名称,从出现的菜单选择[Add|NewItem]功能,屏幕上就会出现要求选择欲加入到项目的项目的窗口,如图1所示:
图1:
要求选择欲加入到项目的项目的窗口
请于中间的窗口选择[GameComponent]项目,于[Name]字段输入文件名,然后按下[Add]键,就可以为项目加入一个继承自GameComponent类别的衍生类别。
[注意]
继承自GameComponent类别的衍生类别无法覆写基础类别的LoadContent方法和Draw方法,适合用来制作没有用户接口的游戏组件。
如果需要制作提供用户接口的游戏组件,可以在为项目加入继承自GameComponent类别的衍生类别之后,自行将所继承的GameComponent基础类别修改成DrawableGameComponent类别,就可以覆写基础类别的LoadContent方法和Draw方法,分别负责执行加载所管理的游戏资源,和绘制游戏内容的工作。
以下就是在继承自DrawableGameComponent类别的衍生类别覆写基础类别的LoadContent方法和Draw方法的范例:
publicclassGameComponent1:
Microsoft.Xna.Framework.DrawableGameComponent
{
…
protectedoverridevoidLoadContent()//覆寫LoadContent方法
{
base.LoadContent();
}
publicoverridevoidDraw(GameTimegameTime)//覆寫Draw方法
{
base.Draw(gameTime);
}
}
GameComponent类别常用的属性可以参考表5的说明:
表5:
GameComponent类别常用的属性
属性名称
说明
Enabled
控制GameComponent类别的对象是否启用的属性。
当对象启用时,类别的Update方法就会被定时地呼叫
UpdateOrder
控制Update方法被呼叫的顺序。
内容值小的对象的Update方法会优先被呼叫
GameComponent类别常用的方法详见表6的说明:
表6:
GameComponent类别常用的方法
方法名称
说明
Initialize
负责执行GameComponent类别的对象初始化的方法
Update
负责更新GameComponent类别的对象的状态的方法
DrawableGameComponent类别的功能和GameComponent类别的功能类似,差别在于DrawableGameComponent类别可以用来管理具用户接口的游戏组件。
DrawableGameComponent类别常用的属性请参考表7的说明:
表7:
DrawableGameComponent类别常用的属性
属性名称
说明
Enabled
控制DrawableGameComponent类别的对象是否启用的属性。
当对象启用时,类别的Update方法就会被定时地呼叫
Visible
控制DrawableGameComponent类别的对象是否隐藏的属性,对象隐藏时,类别的Draw方法将不会被呼叫
UpdateOrder
控制Update方法被呼叫的顺序。
内容值小的对象的Update方法会优先被呼叫
DrawOrder
控制Draw方法被呼叫的顺序。
内容值小的对象的Draw方法会优先被呼叫
Game
取得管理DrawableGameComponent类别的对象的Game类别对象的属性
GraphicsDevice
取得游戏程序使用的绘图装置的属性
DrawableGameComponent类别常用的方法请参考表8的说明:
表8:
DrawableGameComponent类别常用的方法
方法名称
说明
Initialize
负责执行GameComponent类别的对象初始化的方法
LoadContent
负责加载欲使用的游戏资源
UnloadContent
负责释放欲使用的游戏资源
Update
负责更新游戏的状态
Draw
负责显示游戏的内容
制作好GameComponent类别或是DrawableGameComponent类别之后,我们就可以在Game1类别的建构函式中建立GameComponent类别或是DrawableGameComponent类别的对象,再将建立好的对象加入到Game1类别的对象的Components集合中,游戏程序便会定时地呼叫GameComponent类别或是DrawableGameComponent类别的Update方法,以及DrawableGameComponent类别的Draw方法,达到更新游戏状态和显示游戏内容的效果。
假设游戏项目中已经制作好继承自GameComponent类别的衍生类别,名称为GameComponent1,以及继承自DrawableGameComponent类别的衍生类别,名称为DrawableGameComponent1,则Game1类别的建构函式就可以写成以下的样子:
publicGame1()
{
graphics=newGraphicsDeviceManager(this);
Content.RootDirectory="Content";
graphics.PreferredBackBufferHeight=480;
graphics.PreferredBackBufferWidth=800;
Components.Add(newGameComponent1(this));
Components.Add(newDrawableGameComponent1(this));
//Framerateis30fpsbydefaultforWindowsPhone.
TargetElapsedTime=TimeSpan.FromTicks(333333);
}
[提示]
XNAFramework支持的DrawableGameComponent类别虽然可以用来管理游戏程序的人物,但是却没有记录游戏人物坐标位置的属性,程序设计师可以自行于继承自DrawableGameComponent类别的衍生类别加入负责记载游戏人物坐标的属性,以形成一个完整的游戏组件,利于游戏程序进行定位与移动。
显示2D与3D图形
以XNA为基础的游戏程序可以利用Texture2D类别管理2D图形资源,利用Model类别管理3D模型。
用来管理2D图形资源的Texture2D类别常用的属性可以参考表9的说明,用来管理3D模型的Model类别的常用属性可以参考表10的说明:
表9:
Texture2D类别常用的属性
属性名称
说明
Bounds
代表图形资源的大小
Format
代表图形资源的格式
GraphicsDevice
取得游戏程序使用的绘图装置的属性
Height
图形资源的高度(单位:
pixel)
Width
图形资源的宽度(单位:
pixel)
表10:
Model类别的常用属性
属性名称
说明
Bones
3D模型中的骨骼数据的集合
Meshes
3D模型中的网格数据的集合
Root
取得最根源的骨骼数据的属性
坐标
当以XNA为基础的游戏程序欲将所加载的2D或3D图形资源显示到游戏的画面时,我们就会需要用到和坐标有关的型态。
XNA支持的常用坐标类别包括定义2维空间坐标点的Vector2结构,定义3维空间坐标点的Vector3结构,以及定义齐次坐标系统(HomogenousCoordinateSystem)坐标点的Vector4结构。
Vector2架构的是二维空间的坐标,坐标原点默认在窗口的左上角,如图2所示:
图2:
二维空间的坐标系统
Vector2结构的数据成员请参考表11的说明:
表11:
Vector2结构的数据成员
数据成员名称
说明
X
代表坐标点的X轴的位置
Y
代表坐标点的Y轴的位置
Vector2结构常用的方法请参考表12的说明:
表12:
Vector2结构常用的方法
方法名称
说明
Add
对坐标点执行加法运算
Clamp
限制坐标内容值必须落在指定的范围之间
Distance
计算两个坐标点之间的距离
DistanceSquared
计算两个坐标点之间的距离的平方
Divide
对坐标点执行除法运算
Equals
判断坐标点是否等于指定的坐标点
Lerp
计算两个坐标点之间的线性内插
Max
计算坐标点的最大值
Min
计算坐标点的最小值
Multiply
对坐标点执行乘法运算
Negate
对坐标点执行反运算
Subtract
对坐标点执行减法运算
Transform
对坐标点执行转置(Transform)运算
Vector3架构的是三维空间的坐标,因为XNAFramework支持右手坐标系统(Right-HandedSystem),其Z轴往使用者的方向递增,如图3所示:
图3:
XNA支持的右手坐标系统
Vector3结构的数据成员可以参考表13的说明:
表13:
Vector3结构的数据成员
数据成员名称
说明
X
代表坐标点的X轴的位置
Y
代表坐标点的Y轴的位置
Z
代表坐标点的Z轴的位置
Vector3结构常用的方法和Vector2结构常用的方法类似,但是有提供能够计算外积(CrossProduct)的Cross方法。
Vector4架构的是齐次坐标系统(HomogeneousCoordinateSystem)的坐标点,第四个坐标并非用来代表几何空间的位置,而是用来表示坐标轴的远近参数。
Vector4结构的数据成员可以参考表14的说明:
表14:
Vector4结构的数据成员
数据成员名称
说明
X
代表坐标点的X轴的位置
Y
代表坐标点的Y轴的位置
Z
代表坐标点的Z轴的位置
W
W元素。
W元素并不是用来代表几何空间的位置,而是为了定义转置矩阵的设计,利于执行平行、放大、与旋转的处理
Vector4结构常用的方法和Vector2结构常用的方法类似,可以直接参考表12的说明。
卷动游戏程序背景的做法
了解了XNAFramework支持游戏设计的常用类别之后,接下来我们就要使用这些类别为游戏程序制作一个可以自动卷动的背景,就像超级玛璃的游戏一样,在游戏进行时不断地卷动。
要制作游戏的卷动背景,可以准备一张以上,组合起来会变成完整的背景图的背景拼图,例如以下就是由三张连续的背景拼图组成的背景图。
图4:
由三张连续的图片拼凑而成背景图
[说明]
游戏的背景通常是由多张图片拼凑而成,一张接着一张不断地轮播,周而复始。
请注意除非背景图的内容永远不会重复,否则不要使用单一张完整的背景图片当做游戏的背景,就算要制作背景图内容永远不重复的游戏,也会因为单一张完整的图片体积过积而不切实际。
准备好当做游戏背景的背景拼图之后,请启动VisualStudio2010ExpressforWindowsPhone,建立一个[WindowsPhoneGame(4.0)]型态的项目,并把准备好的背景拼图加入到[SolutionExplorer]窗口中的ContentPipeline项目中,以便被游戏程序加载使用。
建立好项目之后请开启Game1.cs原始程序档案进行编辑,于Game1类别中加入以下的变量宣告,分别用来管理当做游戏背景的拼图,以及记载背景拼图位置的变量:
Texture2DBackground1;//管理第一張背景圖片的變數
Texture2DBackground2;//管理第二張背景圖片的變數
Texture2DBackground3;//管理第三張背景圖片的變數
Vector2Position1;//第一張背景圖片的顯示座標
Vector2Position2;//第二張背景圖片的顯示座標
Vector2Position3;//第三張背景圖片的顯示座標
请注意上述的变量宣告可以处理由三张图片拼凑而成的游戏背景,如果游戏背景是由更多图片组成,可以宣告适量的变量以管理组成背景的图片。
宣告好必要的变量之后,请修改Game1类别的建构函式,加入设定游戏窗口大小的程序代码,修改好的建构函式如下:
publicGame1()
{
graphics=newGraphicsDeviceManager(this);
Content.RootDirectory="Content";
graphics.PreferredBackBufferWidth=480;//設定遊戲視窗的寬度為480
graphics.PreferredBackBufferHeight=800;//設定遊戲視窗的寬度為400
//Framerateis30fpsbydefaultforWindowsPhone.
TargetElapsedTime=TimeSpan.FromTicks(333333);
}
设定好游戏窗口的大小之后,请编辑Game1类别的LoadContent方法,负责加载当做背景图片的图形,并设定妥背景图片的显示位置,编辑好的LoadContent方法如下:
protectedoverridevoidLoadContent()
{
//CreateanewSpriteBatch,whichcanbeusedtodrawtextures.
spriteBatch=newSpriteBatch(GraphicsDevice);
//TODO:
usethis.Contenttoloadyourgamecontenthere
Background1=Content.Load("Background01");//載入第一張背景圖片
Position1=newVector2(0,0);//設定第一張背景圖片的顯示位置
Background2=Content.Load("Background02");//載入第二張背景圖片
Position2=newVector2(Position1.X+
Background1.Width,0);//設定第二張背景圖片要顯示在第一張背景圖片的右方
Background3=Content.Load("Background03");//載入第三張背景圖片
Position3=newVector2(Position2.X+
Background2.Width,0);//設定第三張背景圖片要顯示在第二張背景圖片的右方
}
如果读者准备的背景图片的文件名和上述的范例程序代码所指定的文件名不同,请依据所准备的图形文件名修改上述指定加载的文件名。
完成加载游戏程序的背景图案之后,接下来我们必须修改Game1类别的Update方法,更新背景图片显示的位置,创造出背景卷动的效果。
如果要将游戏的背景由右往左卷动,则每一次Update方法被呼叫的时候必须递减所显示的背景图片的左上角点的X坐标的内容值,令背景图片产生往左移动的效果。
反之,如果要将游戏的背景由左往右卷动,则每一次Update方法被呼叫的时候必须递增所显示的背景图片的左上角点的X坐标的内容值,就能够令背景图片产生往右移动的效果。
请注意如果背景图是由右往左卷动,当最左边背景图卷动到游戏的窗口之外时,必须自动补到最右边的图的右边,背景图才能够周而复始地不断地卷动,反之亦然。
图5所示即为最左边的背景图卷动到游戏窗口的范围之外时,自动接续到最右方的背景图的右边继续显示的示意图:
图5:
卷动背景图的做法
了解卷动背景图的做法之后,请将Game1类别的Update方法修改成以下的样,以由右往左的方式卷动背景图:
protectedoverridevoidUpdate(GameTimegameTime)
{
//Allowsthegametoexit
if(GamePad.GetState(PlayerIndex.One).Buttons.Back==ButtonState.Pressed)
this.Exit();
//TODO:
Addyourupdatelogichere
if(Position1.X<-Background1.Width)//如果第一張背景圖離開