如何在 Windows Phone 应用程序中组合 Silverlight 和 XNA Framework
2012/2/9
本主题提供将 Silverlight 和 XNA Framework 组合在一起的基本应用程序的分步创建说明。您可以在 Windows Phone 的代码示例主题中找到这个完成的 Silverlight/XNA Framework 示例。在同一页面上还有一个更详细的示例,名为 MyLittleTeapot,它演示了如何通过响应 Silverlight 输入系统的手势来更新 XNA Framework 内容。
提示: |
|---|
继续之前,请阅读使用组合 Silverlight 和 XNA 的项目模板来了解由本文中使用的项目模板创建的代码。 |
过去,您不得不决定是使用 Silverlight 还是 XNA Framework 来生成 Windows Phone 应用程序。尽管某些类可以在框架之间共享,但针对可视化只能使用一个框架。从 Windows Phone OS 7.1 开始,您便可以使用新的 SharedGraphicsDeviceManager 和 UIElementRenderer 类将 Silverlight 和 XNA Framework 组合到一个应用程序中。
注意: |
|---|
以下过程中的步骤用于 Visual Studio 2010 Express for Windows Phone。 当您使用用于 Visual Studio 2010 Professional 或 Visual Studio 2010 Ultimate 的插件时,您可能会看到菜单命令或窗口布局中的一些微小改变。 |
创建 Windows Phone Silverlight 应用程序的第一步是创建新项目。
创建新项目的步骤
确保下载并安装了 Windows Phone SDK。有关更多信息,请参阅安装 Windows Phone SDK。
从 Windows“开始”菜单启动 Visual Studio 2010 Express for Windows Phone。如果显示“注册”窗口,则可以进行注册或暂时关闭该窗口。
通过选择“文件 | 新建项目”菜单命令来创建一个新项目。
将显示“新建项目”窗口。展开“Visual C#”模板,然后选择“Silverlight for Windows Phone”模板。
选择“Windows Phone Silverlight 和 XNA 应用程序”模板。用您选择的名称填写项目“名称”。

单击“确定”。Visual Studio 将创建一个新项目并在 Visual Studio 设计器窗口中打开 MainPage.xaml。
在创建项目之后,您可能在“警告”窗口中看到一个项目,内容大意为:“该项目的‘SilverlightXNAAppLib’无法被引用。引用项目的目标指向其他框架系列 (.NETFramework)。”您可以安全地忽略此错误。它仅指 Silverlight 和 XNA Framework 程序集之间在命名上的差异。
确保在 Visual Studio 顶部的目标下拉列表中选择“Windows Phone 模拟器”。
按 F5 运行 Windows Phone 模拟器下的项目。
在模拟器中,按“更改到游戏页面”按钮。
默认项目使用 XNA Framework 将 Windows Phone 屏幕清除到 CornflowerBlue 颜色。我们将执行以下操作:
添加用来对屏幕上的矩形进行动画处理的代码
添加用来创建颜色面板的 Silverlight 按钮控件以更改该矩形的颜色
添加一个用来切换颜色面板的可见性的按钮
XNA Framework 将呈现这些控件以及已进行动画处理的矩形。
创建不同颜色的矩形并将其添加到项目的库内容中。
创建新图形库内容的步骤
右键单击以下图形并选择“将图片另存为...”。

在“保存图片”对话框中,导航到您在其中创建项目的目录。
将图片以另存为 XxxxLibContent 目录中的 redRect.jpg,其中 Xxxx 为您在本主题前面“创建新项目”一节的第 5 步中输入的项目名称。
对以下两个图形执行相同的操作,将它们分别另存为 greenRect.jpg 和 blueRect.jpg。


在“解决方案资源管理器”中,右键单击 XxxxLibContent (Content),其中 Xxxx 为您在本主题前面“创建新项目”一节的第 5 步中输入的项目名称。
在上下文菜单中,选择“添加” > “现有项目...”。
在“添加现有项目”对话框中,通过在按下 CTRL 键的同时单击 blueRect.jpg、greenRect.jpg 和 redRect.jpg 来选择所有这 3 个文件。
单击“添加”按钮以将这几个图形文件添加到项目中。
在本节中,我们将以图形内容的形式加载矩形并对当前选择的矩形进行动画处理。
图形的加载和动画处理步骤
在“解决方案资源管理器”中,通过单击 GamePage.xaml 左侧的三角形来展开该展开它。
在代码编辑器中,通过双击 GamePage.xaml.cs 来打开它。
在 GamePage 类中的类范围处声明四个 Texture2D 变量。
// The current rectangle Texture2D texture; // A variety of rectangle colors Texture2D redTexture; Texture2D greenTexture; Texture2D blueTexture;
向下滚动到 OnNavigatedTo 方法。
在 TODO: 注释之后,添加以下代码:
// If texture is null, we've never loaded our content. if (null == texture) { redTexture = contentManager.Load<Texture2D>("redRect"); greenTexture = contentManager.Load<Texture2D>("greenRect"); blueTexture = contentManager.Load<Texture2D>("blueRect"); // Start with the red rectangle. texture = redTexture; }在 GamePage 类中的类范围处声明两个 Vector2 变量。
// Used to move the rectangle around the screen Vector2 spritePosition; Vector2 spriteSpeed = new Vector2(100.0f, 100.0f);
用以下代码替换 OnUpdate 方法的内容。
// Move the sprite by speed, scaled by elapsed time. spritePosition += spriteSpeed * (float)e.ElapsedTime.TotalSeconds; int MinX = 0; int MinY = 0; int MaxX = SharedGraphicsDeviceManager.Current.GraphicsDevice.Viewport.Width - texture.Width; int MaxY = SharedGraphicsDeviceManager.Current.GraphicsDevice.Viewport.Height - texture.Height; // Check for bounce. if (spritePosition.X > MaxX) { spriteSpeed.X *= -1; spritePosition.X = MaxX; } else if (spritePosition.X < MinX) { spriteSpeed.X *= -1; spritePosition.X = MinX; } if (spritePosition.Y > MaxY) { spriteSpeed.Y *= -1; spritePosition.Y = MaxY; } else if (spritePosition.Y < MinY) { spriteSpeed.Y *= -1; spritePosition.Y = MinY; }用以下代码替换 OnDraw 方法的内容。
SharedGraphicsDeviceManager.Current.GraphicsDevice.Clear(Color.Black); // Draw the sprite spriteBatch.Begin(); // Draw the rectangle in its new position spriteBatch.Draw(texture, spritePosition, Color.White); spriteBatch.End();
选择“Windows Phone 模拟器”作为目标并按 F5 来运行您的应用程序。单击“更改到游戏页面”按钮,您应该看到与下图非常类似的内容。

在本节中,我们使用 XAML 来创建 Silverlight Button 控件的面板。这些按钮使用户能够更改矩形的颜色。我们还将添加一个用来切换颜色面板的可见性的按钮。使用 UIElementRenderer 类,将这些控件呈现到 Texture2D,然后采用 OnDraw 方法中的 SpriteBatch 操作在屏幕上绘制这些控件。
添加 Silverlight 控件的步骤
在“解决方案资源管理器”中,双击 GamePage.xaml 以在设计器中打开它。
由于我们将使用 XAML,因此将以下注释:
<!--No XAML content as the page is rendered entirely with XNA-->
替换为以下 XAML 代码。
<!-- LayoutRoot is the root grid where all page content is placed. --> <Grid x:Name="LayoutRoot"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <!-- Toggle the visibility of the ColorPanel. --> <Button Grid.Row="0" x:Name="ColorPanelToggleButton" Click="ColorPanelToggleButton_Click" Margin="1,0,-1,0">Toggle Color Panel</Button> <!-- Arrange buttons in a horizontal line by using StackPanel. --> <StackPanel x:Name="ColorPanel" Grid.Row="2" Height="100" Orientation="Horizontal" HorizontalAlignment="Center" Visibility="Visible"> <!-- Buttons to set the rectangle to specific colors --> <Button Click="redButton_Click" HorizontalAlignment="Center" Height="75" VerticalAlignment="Center" BorderThickness="3" Background="Red" Width="75" /> <Button Click="greenButton_Click" HorizontalAlignment="Center" Height="75" VerticalAlignment="Center" BorderThickness="3" Background="Lime" Width="75" /> <Button Click="blueButton_Click" HorizontalAlignment="Center" Height="75" VerticalAlignment="Center" BorderThickness="3" Background="Blue" Width="75" /> </StackPanel> </Grid>该 XAML 代码创建一个 Grid 元素以包含所有其他元素。首先定义 Grid 包含三行。通过使用 Auto 关键字,按内容定义首行和底行的 Height 属性。对中间行的 Height 属性使用星号 (*) 将使该行占用其他两行之间剩余的所有空间。
接下来,XAML 通过将 Click 事件处理程序设置为名为 ColorPanelToggleButton_Click 的方法来定义一个 Button。
然后,XAML 定义一个 StackPanel 以包含组成我们的颜色面板的 Button 元素。StackPanel 将 x:Name 属性设置为 ColorPanel。在 C# 代码中使用该名称来切换该面板的可见性。
Button 元素都设置了 Background 颜色并分配了 Click 事件处理程序。
下图显示了我们的应用程序在设计器中的外观。

既然我们已经添加了控件并向 Click 事件处理程序分配了名称,那么接下来我们需要实现处理程序方法。
添加事件处理程序的步骤
在 Visual Studio 代码编辑器中,打开或切换到 GamePage.xaml.cs。
向下滚动到文件结尾,经过 OnDraw 方法。
复制以下代码并将其粘贴到 OnDraw 方法后面。
// Toggle the visibility of the StackPanel named "ColorPanel". private void ColorPanelToggleButton_Click(object sender, RoutedEventArgs e) { if (System.Windows.Visibility.Visible == ColorPanel.Visibility) { ColorPanel.Visibility = System.Windows.Visibility.Collapsed; } else { ColorPanel.Visibility = System.Windows.Visibility.Visible; } }该代码只是切换 StackPanel(我们在 XAML 代码中命名为“ColorPanel”)上的 Visibility 属性。
在 ControlPanelToggleButton_Click 处理程序后面,复制并粘贴我们在 XAML 中声明的颜色 Button 元素的以下三个 Click 处理程序。
// Switch to the red rectangle. private void redButton_Click(object sender, RoutedEventArgs e) { texture = redTexture; } // Switch to the green rectangle. private void greenButton_Click(object sender, RoutedEventArgs e) { texture = greenTexture; } // Switch to the blue rectangle. private void blueButton_Click(object sender, RoutedEventArgs e) { texture = blueTexture; }这些事件处理程序只是将我们用于在屏幕上呈现矩形的 Texture2D 对象(称为“纹理”)设置为指向我们已在 OnNavigatedTo 方法中加载的相应颜色的矩形。
既然我们已经创建了控件并对事件处理程序进行了编码,那么接下来我们所需要做的就是在屏幕上呈现它们。
呈现 Silverlight 控件的步骤
在 GamePage.xaml.cs 文件中,在 GamePage 类的类范围级别声明一个 UIElementRenderer。
// For rendering the XAML onto a texture UIElementRenderer elementRenderer;
在 GamePage 类构造函数中,声明 LayoutUpdated 事件的一个处理程序。
// Use the LayoutUpdate event to know when the page layout // has completed so that we can create the UIElementRenderer. LayoutUpdated += new EventHandler(GamePage_LayoutUpdated);
实现 GamePage_LayoutUpdated 事件处理程序。在调用 UIElementRenderer 构造函数时,this 参数指的是 GamePage 类,该类的一部分是通过 GamePage.xaml 文件中的 XAML 代码定义的。UIElementRenderer 类带有从 UIElement 派生的 XAML 元素并将这些元素呈现到 Texture2D 对象。
void GamePage_LayoutUpdated(object sender, EventArgs e) { // Create the UIElementRenderer to draw the XAML page to a texture. // Check for 0 because when we navigate away the LayoutUpdate event // is raised but ActualWidth and ActualHeight will be 0 in that case. if ((ActualWidth > 0) && (ActualHeight > 0)) { SharedGraphicsDeviceManager.Current.PreferredBackBufferWidth = (int)ActualWidth; SharedGraphicsDeviceManager.Current.PreferredBackBufferHeight = (int)ActualHeight; } if (null == elementRenderer) { elementRenderer = new UIElementRenderer(this, (int)ActualWidth, (int)ActualHeight); } }
注意:您不能从可视化树移除在 UIElementRenderer 构造函数中指定的 Silverlight UIElement。
接下来,使用 UIElementRenderer 实例在屏幕上绘制 Silverlight 控件。在 GamePage.xaml.cs 文件中找到 OnDraw 方法。在调用 spriteBatch.Begin 之前,添加以下代码行。这是将 XAML 实际呈现到缓冲区中的代码,可以通过 UIElementRenderer 的 Texture 属性进行访问。
// Render the Silverlight controls using the UIElementRenderer. elementRenderer.Render();
而且,在 OnDraw 方法中,在对 spriteBatch.Begin 和 spriteBatch.End 的调用之间添加以下代码行。
// Using the texture from the UIElementRenderer, // draw the Silverlight controls to the screen. spriteBatch.Draw(elementRenderer.Texture, Vector2.Zero, Color.White);
选择“Windows Phone 模拟器”作为目标并按 F5 来运行您的应用程序。您应该看到与以下图形非常相似的内容。

单击位于应用程序底部的颜色面板中的按钮可切换已进行动画处理的矩形的颜色。
单击位于应用程序顶部的 Toggle Color Panel 按钮可隐藏和显示颜色面板。