从构思到发布 开发Windows Phone 7小游戏.docx
- 文档编号:11175121
- 上传时间:2023-02-25
- 格式:DOCX
- 页数:18
- 大小:212.92KB
从构思到发布 开发Windows Phone 7小游戏.docx
《从构思到发布 开发Windows Phone 7小游戏.docx》由会员分享,可在线阅读,更多相关《从构思到发布 开发Windows Phone 7小游戏.docx(18页珍藏版)》请在冰豆网上搜索。
从构思到发布开发WindowsPhone7小游戏
从构思到发布开发WindowsPhone7小游戏
2011-05-0411:
31布加迪编译 51CTO.com 字号:
T | T
本文介绍了WindowsPhone7平台游戏开发过程的整个周期,从游戏构思开始,到游戏发布到WindowsPhoneMarketplace结束,这个过程的任何细节都不会遗漏。
AD:
2013云计算架构师峰会课程资料下载
【51CTO译文】引言
到底能多快地为运行WindowsPhone7的现代化手机开发一款功能完备的游戏?
为此你需要具备什么条件?
又会面临什么样的难题?
我们将在开发小游戏期间力图解答上述问题。
为了营造一种实际的环境,这个功能完备的应用程序开发后将提交到WindowsPhoneMarketplace。
我们将审查游戏开发过程的整个周期,从游戏构思开始,到游戏发布到Marketplace结束,这个过程的任何细节都不会遗漏。
游戏构思
我们不会仿效其他游戏。
我们考虑的是开发一款新颖、有趣、绚丽的游戏——是专门为使用方向感应器和触摸屏的手机而开发的。
你只要将手机往不同的侧边倾斜,就可以在方向感应器的帮助下操纵小球,好像小球就在方形盒子里面滚动。
画面上有多个彩球。
它们试图撞到白球,给白球着上自己的颜色。
用户只要用指尖点一下彩球,就可以击碎彩球。
你点一下球后,就会变成色彩鲜艳的飞溅物,然后会消失,之后新的球会出现。
每击碎一个球,就能得到更高的分数。
用户能玩的关卡数量没有限制。
玩家的目标应该是得到尽可能高的分数。
为了让玩家可以使用方向感应器(而不仅仅击碎球),为游戏添加了更多的球(黑球)。
除非黑球被着上别的颜色,否则不会被击碎。
2D图形对这款游戏来说绰绰有余。
此外,需要播放音乐,与方向感应器和触摸屏进行交互。
开发环境
为了针对WindowsPhone7开发应用程序,我们需要VisualC#2010简易版和WindowsPhone开发者工具(WindowsPhoneDeveloperTools)。
两者都是免费产品。
然后进入到微软网站,下载和安装下列工具:
WindowsPhone开发者工具无法安装到WindowsXP上,不过你可以采取这个办法。
然而,手机模拟器可能无法在WindowsXP上运行,因而最好还是安装Windows7。
如果你已经拥有VisualStudio2010,最好在上面安装WindowsPhone开发者工具,因为VisualC#2010简易版用起来明显更不方便。
技术选择:
XNA对决Silverlight
安装了WindowsPhone开发者工具后,可以选择用Studio来创建新的项目类型:
WindowsPhone应用程序(WindowsPhoneApplication)和WindowsPhone游戏(WindowsPhoneGame)。
哪一个更适合我们呢?
第一个项目是面向WindowsPhone7的Silverlight应用程序。
相应地,它可以访问几乎所有的类,这些类在通常的Silverlight中得到表示。
它有XAML和控件以及Studio中的设计器等。
第二个项目是XNA4.0.应用程序。
它没有任何控件;不过,它有游戏周期,可以快速访问硬件图形的功能特性。
从名称和技术描述来判断,我们需要的是XNA。
Silverlight有没有可能也适合开发游戏?
用SilverlightforWindowsPhone简单测试一下,就会发现这项技术的局限性:
数百个同时运动的小图像让手机进入幻灯片模式。
如果我们用XNA进行同样的测试,一切都快速运行(拥有数量更多的图像)。
这就是为什么我们用XNA来开发游戏。
遗憾的是,没有控件;但目前看来控件也没什么用处。
上手XNA
我们不妨用Studio来创建WindowsPhone游戏项目。
该项目与游戏类一同出现:
publicclassGame1:
Microsoft.Xna.Framework.Game
不妨定义用户在玩游戏期间如何握持手机。
假设一只手握持手机(旋转手机即可操纵白球)、另一只手点彩球更为舒适。
这意味着,我们需要纵向游戏模式。
我们为游戏构建器添加了这种模式。
1.public Game1()
2.
3.{
4.
5.graphics = new GraphicsDeviceManager(this);
6.
7.Content.RootDirectory = "Content";
8.
9.graphics.SupportedOrientations = DisplayOrientation.Portrait;
10.
11.graphics.PreferredBackBufferWidth = 480;
12.
13.graphics.PreferredBackBufferHeight = 800;
14.
15.graphics.IsFullScreen = true;
16.
17.}
然后在这个类中,我们最感兴趣的是两项功能:
Update(更新)和Draw(绘制)。
1.protected override void Update(GameTime gameTime)
2.
3.{
4.
5.// Allows the game to exit(允许游戏退出)
6.
7.if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
8.
9.this.Exit();
10.
11.// TODO:
Add your update logic here(TODO:
在这里添加更新逻辑)
12.
13.base.Update(gameTime);
14.
15.}
16.
17.protected override void Draw(GameTime gameTime)
18.
19.{
20.
21.GraphicsDevice.Clear(Color.CornflowerBlue);
22.
23.// TODO:
Add your drawing code here(TODO:
在这里添加绘制代码)
24.
25.base.Draw(gameTime);
26.
27.}
第一项功能专门用于游戏逻辑处理。
我们会得到用户动作(从方向感应器到触摸屏)方面的数据,并算出所有游戏物体的新位置。
第二项功能专门用于绘制屏幕上的游戏物体。
有必要说明:
这两项功能执行的总时间不该超过游戏周期的一次迭代。
这在手机上相当于33毫秒,因为游戏周期的频率是每秒30帧。
如果功能执行的时间超过这个值,游戏速度就会很慢,一些帧就会被遗漏,或者更糟糕的是,游戏会忽略用户动作。
这个游戏实际上是实时应用程序。
它对垃圾收集器(GarbageCollector)的动作会有怎样的反应?
最好是避免垃圾收集器突然干预的情况,那样我们可以顺利地处理物体,不用在每次迭代时创建成千上万物体。
一般来说,我们不需要经常创建物体,因为游戏世界的所有物体相对来说历时长久。
我们会使用已有物体的结构或链接作为特征参数。
这样一来,垃圾收集器不会阻止我们做所需的动作。
我们不妨试着编译和启动应用程程序。
在几台电脑上,你可能会看到表明XNA无法在模拟器上启动的消息。
这样一来,你可能要创建Windows游戏项目,并附加来自WindowsPhone游戏项目的文件(AddAsLink,即添加为链接)。
同样这些XNA代码可以在手机和Windows(以及XBOX360)上运行。
最后,有一个窗口填满了紫色。
这是由于GraphicsDevice.Clear(Color.CornflowerBlue)功能执行的结果。
游戏类中有一个SpriteBatch对象类。
我们在绘制时需要这个对象。
它含有处理2D图形和文本的所有必要方法。
不过我们仍缺少最重要的方面:
游戏内容。
游戏内容
游戏内容是游戏必不可少的不同资源,比如纹理(用于绘制的图像)、字体(输出文本时需要)和声音。
我们在创建WindowsPhone游戏项目的同时,还创建了名称是“Content”的另一个项目。
我们应该为这个项目添加图像和声音文件。
此外,我们应该设定用于这个项目中文本输出的所有字体。
在Content.Load(assetName)函数的帮助下,将内容装入到程序很简单。
游戏类中拥有Content属性。
我们连同内容添加到项目中的资源名称应该设成assetName。
通常来说,这仅仅是没有扩展名的文件名。
要使用的内容类型(Texture2D、SpriteFont或SoundEffect)应该设成T。
内容装入不是一种快速操作,这就是为什么我们在游戏开始时会装入所有内容,以便需要时可以使用。
现在一切已准备好,我们可以开始开发游戏了。
游戏逻辑
所有游戏逻辑都可以放入到GameController这个单独的类中。
现在,游戏类中的Update功能看起来如同这样:
1.protected override void Update(GameTime gameTime)
2.
3.{
4.
5.// Allows the game to exit(允许游戏退出)
6.
7.if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
8.
9.this.Exit();
10.
11.GameController.Update(gameTime);
12.
13.base.Update(gameTime);
14.
15.}
注意:
我们把GameTime类的对象发送到GameController.Update。
它拥有ElapsedGameTime属性,该发展表明自上一次调用Update功能上以来过去了多长时间。
这个时间通常是固定的,相当于手机上的33毫秒。
不过,最好不要依靠它,而是在所有计算中都使用发送的值。
我们在需要计算游戏世界物体的运动时,将使用ElapsedGameTime。
比如说,如果我们需要计算白球的新位置(受手机倾斜的影响),它看起来会这样:
position+=(float)(acceleration*gameTime.ElapsedGameTime.TotalSeconds);
小球和飞溅物(它们一出现)的半径按这种方式来计算:
radius+=(float)(GrowSpeed*gameTime.ElapsedGameTime.TotalSeconds);
所有计算会用不同的类来进行。
每个类都有各自相似的Update(gameTime)功能。
GameController.Update会调用它们。
绘制图形
绘制图形发送到GameController类。
游戏类中的Draw功能现在看起来这样:
1.protected override void Draw(GameTime gameTime)
2.
3.{
4.
5.GraphicsDevice.Clear(Color.Black);
6.
7.spriteBatch.Begin();
8.
9.GameController.Draw(spriteBatch);
10.
11.spriteBatch.End();
12.
13.base.Draw(gameTime);
14.
15.}
注意:
我们只将SpriteBatch对象类发送到GameController.Draw。
它只用于绘制。
我们这里不需要GameTime,因为所有必要的计算已经在Update功能中进行。
随后,GameController.Draw会从得到游戏世界逻辑的类调用相似的Draw(spriteBatch)功能。
绘制本身看起来相当简单:
spriteBatch.Draw(texture,position,color);
这时我们只能显示准备好的纹理。
绘制2D基本图形(直线、长方形和椭圆形等)的功能并不由XNA来提供。
可以通过从内容装入纹理来得到纹理:
Texture2Dtexture=Content.Load(assetName);
纹理已经被装入了;所有位置已被计算出来;不过,我们可以“调整”颜色!
如果我们需要原始纹理颜色,就要有Color.White。
如果我们需要另一种颜色,应该用这种颜色布局来绘制纹理。
如果我们要用阿尔法通道(alphachannel)来设定颜色,那么就能透明地绘制纹理。
那样,我们就能轻松自如地显现和隐匿物体以及颜色变化(这些正是我们在游戏中需要的)。
为了混合两种颜色,我们使用Color.Lerp函数。
为了增加阿尔法通道,应使用Color.FromNonPremultiplied函数。
另外还有spriteBatch.Draw函数的其他变种,允许变化和扩展文本,这也是我们的游戏所需要的。
文本输出
文本输出就跟图形输出一样简单:
spriteBatch.DrawString(spriteFont,text,position,color);
你可以通过从内容装入SpriteFont类的对象来得到对象:
SpriteFontspriteFont=Content.Load(assetName);
你还可以在这里以同样的方式设置字体颜色。
如果你用阿尔法通道设置颜色,文本将是透明的。
如果你用浮动位置设置文本输出的坐标,那么文本在显示时可能会有点失真。
这就是为什么在流畅的文本移动没必要时,我们要将坐标舍入到整数。
spriteBatch.DrawString函数有其他变种,允许改变和扩展文本。
有必要记住:
这种运动会引起文本表述错误。
之所以会出现这种情况,是因为XNA并不处理原始向量字体,但能处理栅格表示;项目一编译好,就会创建栅格,随后添加到内容中。
触摸屏
为了定义用户在何处点击屏幕,应该从Microsoft.Xna.Framework.Input.Touch.TouchPanel类得到数据:
1.foreach (var item in TouchPanel.GetState())
2.
3.{
4.
5.if (item.State == TouchLocationState.Pressed
6.
7.|| item.State == TouchLocationState.Moved)
8.
9.{
10.
11.// Get item.Position(得到item.Postion)
12.
13.}
14.
15.}
因此,我们就能得到用户触摸的所有屏幕点。
不过,我们需要关于屏幕触摸一次性动作(点击、在屏幕上移动手指时)的数据。
这些数据是跟踪屏幕按钮(比如暂停按钮)触摸所必可不少的。
为了得到这些数据,应使用手势支持。
在游戏开始时,应该表明我们需要支持手势(点击):
TouchPanel.EnabledGestures=GestureType.Tap;
然后,我们可以在游戏周期的每次迭代得到手势:
1.while (TouchPanel.IsGestureAvailable)
2.
3.{
4.
5.GestureSample gesture = TouchPanel.ReadGesture();
6.
7.if (gesture.GestureType == GestureType.Tap)
8.
9.{
10.
11.// Get guesture.Position(得到guesture.Position)
12.
13.}
14.
15.}
方向感应器
为了得到关于手机倾斜的数据,就要使用Microsoft.Devices.Sensors.Accelerometer类。
遗憾的是,我们无法直接从方向感应器得到数据,因为它只支持事件模式。
这就是为什么应该使用创建对象和订阅事件的附属类:
1.accelerometer = new Microsoft.Devices.Sensors.Accelerometer();
2.
3.accelerometer.ReadingChanged += AccelerometerChanged;
4.
5.accelerometer.Start();
在事件处理器中,我们会记住加速值,并保存起来,以便以后使用:
1.private void AccelerometerChanged(object sender, AccelerometerReadingEventArgs e)
2.
3.{
4.
5.vector = new Vector3((float)e.X, (float)e.Y, (float)e.Z);
6.
7.}
加速向量含有三个轴(X轴、Y轴和Z轴)的信息,但我们先只需要头两个轴(用于手机的纵向模式)。
这就是为什么在我们的坐标系中返回加速的属性看起来这样:
1.public Vector2 Acceleration
2.
3.{
4.
5.get
6.
7.{
8.
9.return new Vector2(vector.X, -vector.Y);
10.
11.}
12.
13.}
是的,这个加速会被施加于白球。
播放声音
可以在SoundEffect类的对象中Play函数的帮助下,播放XNA中的声音。
这个类的对象可以从内容装入:
SoundEffectsound=Content.Load(assetName);
只要这么处理,就可以播放声音了。
窗口
许多东西已准备好:
白球通过方向感应器来运动,其余球会追白球;一旦撞上,就会变成飞溅物,会计算分数,随后播放声音。
看起来像是一切准备就绪?
不,没有这么简单。
现在我们需要创建窗口;开始窗口(主菜单)、暂停对话窗口和游戏结束窗口(显示得分数和记录)。
面向WindowsPhone的XNA没有窗口,这就是为什么我们得自己创建窗口。
不过,实际创建起来比较简单。
用Parent、Children、Bounds、Visible和Enabled这些主要功能以及Update和Draw两个函数创建一个基本控件就够了。
然后,应该创建几个子类:
Window、Button和Label等。
之后,就很容易在窗口中显示元素。
保存游戏状态
手机上的游戏可以随时暂停,只要点击Home按钮或借助其他任何外部事件。
这就是为什么我们要注意随时保存游戏状态,等游戏启动后,可以进一步恢复这个状态。
不妨使用System.IO.IsolatedStorage.IsolatedStorageSettings.ApplicationSettings类来保存状态(及设置)。
这个类实现了IDictionary接口。
我们不妨把所有游戏世界物体(但愿物体数量不多)的的当前状态概括到这个词典中,并调用IsolatedStorageSettings.ApplicationSettings.Save()函数。
退出游戏时,游戏会保存起来。
为此,不妨覆盖游戏类中的OnExiting函数:
1.protected override void OnExiting(object sender, EventArgs args)
2.
3.{
4.
5.GameController.SaveState();
6.
7.base.OnExiting(sender, args);
8.
9.}
游戏恢复以类似方式进行。
应用程序启动时,我们收到来自IsolatedStorageSettings.ApplicationSettings的数据,恢复所有游戏世界物体。
应用程序的激活和停用
我们的这个应用程序并不总是处于活动状态。
有时它可能被停用了(比如来电时),需要再次激活。
为了跟踪这些事件,不妨覆盖游戏类中的OnActivated函数和OnDeactivated函数。
在应用程序停用期间,我们让游戏处于暂停模式,那样用户回来后,关于恢复游戏的对话消息会出现。
此外,为了不浪费处于停用状态的手机的计算资源,我们在游戏类中Update函数的开头添加下列代码:
1.if (!
IsActive)
2.
3.{
4.
5.SuppressDraw();
6.
7.return;
8.
9.}
启动画面
我们的游戏(确切地说,是游戏内容)在几秒钟内装入,在这个装入期间只显示黑色屏幕。
我们应该向用户表明应用程序在运行中。
为此,应该绘制一个漂亮的启动画面(splashscreen),在游戏启动时显示:
如果你只是往Silverlight应用程序里面添加针对WindowsPhone的SplashScreenImage.jpg文件,启动画面会自动显示。
不过这对XNA项目来说行不通。
我们得改动内容的装入。
首先,我们为启动画面做好纹理,然后在第一次调用Draw函数的过程中绘制纹理。
然后,我们装入其余内容,启动游戏。
直到其余内容都装入,启动画面才显示。
现在,这个游戏看起来漂亮多了。
手机中的游戏位置
为了让我们的游戏出现在手机中的Games部分(只要点击手机开始屏幕上的XBOXLIVE按钮,就能访问它),需要编辑项目中的WMAppManifest.xml文件。
应该在这个文件中,而不是在Genre="Apps.Normal"这一行中编写Genre="Apps.Games"。
另外我们把游戏名称和描述放入到同一个文件(分别是Title和Description属性)。
删除不必要的需求(section)。
在这个部分中,我们只留下方向感应器支持。
这个版本的游戏不需要其他部分。
该项目应该有两幅图片:
GameThumbnail.png和Background.png。
Games部分的游戏显示区需要第一幅图片。
手机的开始屏幕需要第二幅图片。
这两幅图片的大小都应该是173×173像素。
试用模式
由于我们开发的这个游戏将是收费游戏,需要添加试用模式支持。
试用功能已经内置到平台中,在Microsoft.Phone.Marketplace.LicenseInformation类的帮助下完成:
1.var license = new Microsoft.Phone.Marketplace.LicenseInformation();
2.
3.return license.IsTrial();
由于该函数相当慢,我们不会在每次游戏
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 从构思到发布 开发Windows Phone 7小游戏 构思 发布 开发 Windows 小游戏