马宁的Windows Phone 7.1初体验——XNA与Silverlight集成

关于Windows Phone Mango真真假假的图片、视频已经在网上流传很久了,微软发布的Windows Phone 7.1 SDK可以让我们看到一部分Mango支持的功能。
普通用户对Mango的关注更多停留在多语言、多任务等方面,但对于开发者来说,Mango还有很多有趣的功能。我会试着将自己感兴趣的一些功能写出来,变成一个系列。
首先,大家要安装Windows Phone 7的SDK和Windows Phone 7.1 SDK的Beta 版,下载地址如下:
http://www.microsoft.com/downloads/en/details.aspx?FamilyID=77586864-ab15-40e1-bc38-713a95a56a05

创建工程

关于Windows Phone 7.1的第一个功能是XNA与Silverlight的集成。Windows Phone里有两个Framework,Silverlight是做应用的,而XNA是做游戏开发的。Silverlight有一套非常好用的UI设计工具和控件体系,而XNA对于动画效果的处理又远远超过Silverlight。但是在WP7里,Silverlight和XNA必须是分开的,所以当Silverlight应用需要高性能显示,或者XNA游戏里需要编写UI时,都会碰到很多困难。
于是,在WP 7.1里,提供了XNA与Silverlight集成的功能。接下来,我们就来看一下,如何创建一个Silverlight和XNA集成的应用。
打开Visual Studio 2010,选择File-New Project,在Visual C#里找到Silverlight for Windows Phone,然后选择其中的“Windows Phone 3D Graphics Application”,这个名字有足够的迷惑性,XNA的2D也是支持的。如下图:
2马宁的Windows Phone 7.1初体验——XNA与Silverlight集成
创建过程没有什么特殊的地方,创建完成后的工程如下图所示:
32马宁的Windows Phone 7.1初体验——XNA与Silverlight集成
说实话,XNA与Silverlight集成的实现并不算优雅,有点叠床架屋的感觉。整个Solution里分为三个Project,其中GraphicsApp1是我们的主程序,主要的逻辑代码都是在这个工程里的,这是一个典型的Silverlight程序,包含了App.xaml和MainPage.xmal,多出来一个GamePage.xaml,这个是XNA的页面。除此之外,还有两个Library,分别叫做GraphicsApp1Library和GraphicsApp1LibraryContent,后边是XNA的Content库,前边一个应该是为了能够让Silverlight加载XNA资源所做的适配库。
直接运行程序,我们会看到下面的界面,点击HomePage的Play按钮,我们就进入了XNA的GamePage界面:
432马宁的Windows Phone 7.1初体验——XNA与Silverlight集成 5432马宁的Windows Phone 7.1初体验——XNA与Silverlight集成

GamePage探秘

接下来,我们看一下GamePage.xaml的结构,看看这个看似普通的XAML页面里具体做了什么事情。首先是GamePage.xaml,如下:


什么都没有……所有的显示都是由XNA控制的。接下来,我们去看GamePage.xaml.cs,首先来看引用程序集的部分:
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics;
引用了三个XNA的命名空间,接下来是变量声明:
GameTimer timer; ContentManager content; SpriteBatch spriteBatch; Texture2D texture; Vector2 spritePosition;
除了GameTimer是生面孔外,其他几个都是老熟人,GameTimer也好理解,Silverlight是事件驱动的Framework,如果想定时更新的话,必须要加入一个Timer。接下来,是GamePage的构造函数:
public GamePage() { InitializeComponent(); // Get the application's ContentManager content = (Application.Current as App).Content; // Create a timer for this page timer = new GameTimer(); timer.UpdateInterval = TimeSpan.FromTicks(333333); timer.Update += _disibledevent=> ContentManager对象是来自于App的Content属性,我们不会再有一个派生自Microsoft.Xna.Framework.Game的Host类了。然后是GameTimer的初始化工作,指定更新时间间隔,然后为Update和Draw事件添加方法。我不知道理解的是否正确,但有可能是GameTimer类重新实现了XNA Framework的机制。
然后是两个重载的Navigated函数:
protected override void _disibledevent=>// Set the sharing mode of the graphics device to turn _disibledevent=>true); // Create a new SpriteBatch, which can be used to draw textures. spriteBatch = new SpriteBatch(SharedGraphicsDeviceManager.Current.GraphicsDevice); // TODO: use this.content to load your game content here // Start the timer timer.Start(); base.OnNavigatedTo(e); } protected override void _disibledevent=>// Stop the timer timer.Stop(); // Set the sharing mode of the graphics device to turn off XNA rendering SharedGraphicsDeviceManager.Current.GraphicsDevice.SetSharingMode(false); base.OnNavigatedFrom(e); }

OnNavigatedTo函数实现了LoadContent的功能,第一句话值得注意,我们要首先打开GraphicsDevice的SetSharingMode为true,才能够让XNA元素正常的显示出来。这句话也交代了XNA最主要的类GraphicsDeviceManager的去向,被放到一个静态的SharedGraphicsDeviceManager对象里去了。
创建SpriteBatch和加载资源的过程不再叙述,最后要调用GameTimer的Start方法,来启动XNA的时间驱动机制,与之对应的是OnNavigatedFrom函数中,我们还需要调用GameTimer的Stop方法,来关闭时间驱动机制。
最后是熟悉的OnUpdate和OnDraw方法,就数这两个函数原汁原味地保留了XNA的特点。
/// /// Allows the page to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// private void _disibledevent=>object sender, GameTimerEventArgs e) { // TODO: Add your update logic here } /// /// Allows the page to draw itself. /// private void _disibledevent=>object sender, GameTimerEventArgs e) { SharedGraphicsDeviceManager.Current.GraphicsDevice.Clear(Microsoft.Xna.Framework.Color.CornflowerBlue); // TODO: Add your drawing code here }

添加Silverlight控件

如果只是在Silverlight应用里添加一个XNA的页面,恐怕还没有太大的吸引力。我们还应该让XNA和Silverlight能够在一个页面上显示。首先我们要打开GamePage.xaml文件,找到下面的代码:
将下列代码替换上面的注释:

最新评论

发表评论