| Невозможно пройти тесты, в окне с вопросами пусто |
Совместное использование Silverlight и XNA
Цель работы: Научиться разрабатывать приложения с использованием шаблона Приложение Silverlight и XNA для Windows Phone
35.1. Особенности проекта Приложение Silverlight и XNA для Windows Phone
В некоторых из предыдущих проектов мы использовали отдельные библиотеки и объекты XNA в Silverlight-приложениях. Начиная с Windows Phone OS 7.1. при разработке приложений можно в полной мере пользоваться возможностями Silverlight и XNA в одном приложении. Например, можно создать сложный пользовательский интерфейс на Silverlight, и, в то же время, организовать вывод графики с помощью средств XNA. Фактически, такое приложение позволяет взять всё лучшее от обеих технологий.
Рассмотрим особенности таких приложений. Создадим новый проект, в окне создания проекта выберем шаблон Приложение Silverlight и XNA для Windows Phone, рис. 35.1.
Посмотрим на Обозреватель решений этого проекта, рис. 35.2
Если рассмотреть это решение в первом приближении, то окажется, что мы имеем Silverlight-проект, в котором есть механизмы для визуализации средствами XNA и страница GamePage.xaml, код которой (GamePage.xaml.cs) представляет собой реализацию игрового цикла XNA. Весь вывод данных на этой странице формируется средствами XNA.
Рассмотрим решение подробнее. Оно состоит из трёх проектов:
- Основной проект приложения (P28_1). Это проект приложения, здесь содержатся страницы приложения. Причём, страница MainPage – это обычная Silverlight-страница, которая отображается после запуска приложения, на ней, по умолчанию, расположена кнопка для вызова страницы GamePage.
- Проект библиотеки XNA (P28_1Lib). Этот проект напоминает проект XNA, разработкой которых мы занимались ранее в этом курсе. Он имеет ссылку на проект контента. Этот проект представляет собой нечто вроде моста между Silverlight-приложением и хранилищем контента.
- Проект контента XNA (P281Lib_Content). Традиционный для XNA-приложений проект, содержащий контент – изображения, звуки, трехмерные модели.
Рассмотрим файлы, которые входят в решение. Начнём с файла App.xaml, листинге 35.1.
<Application
x:Class="P28_1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:xna="clr-namespace:Microsoft.Xna.Framework;assembly=Microsoft.Xna.Framework.Interop">
<!--Ресурсы приложения-->
<Application.Resources>
</Application.Resources>
<Application.ApplicationLifetimeObjects>
<!--Обязательный объект, обрабатывающий события времени жизни приложения-->
<shell:PhoneApplicationService
Launching="Application_Launching" Closing="Application_Closing"
Activated="Application_Activated" Deactivated="Application_Deactivated"/>
<!--SharedGraphicsDeviceManager используется для отображения с помощью графических API XNA-->
<xna:SharedGraphicsDeviceManager />
</Application.ApplicationLifetimeObjects>
</Application>
Листинг
35.1.
Файл App.xaml
Этот файл, как и в случае с обычным Silverlight-приложением, определяет обработчики события, касающиеся жизненного цикла приложения, и, кроме того, определяет xna:SharedGraphicsDeviceManager – объект, который используется для вывода XNA-графики.
В листинге 35.2 приведен файл App.xaml.cs,
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
namespace P28_1
{
public partial class App : Application
{
/// <summary>
/// Обеспечивает быстрый доступ к корневому кадру приложения телефона.
/// </summary>
/// <returns>Корневой кадр приложения телефона.</returns>
public PhoneApplicationFrame RootFrame { get; private set; }
/// <summary>
/// Предоставляет приложению доступ к ContentManager.
/// </summary>
public ContentManager Content { get; private set; }
/// <summary>
/// Предоставляет доступ к GameTimer, настроенному для передачи данных в FrameworkDispatcher.
/// </summary>
public GameTimer FrameworkDispatcherTimer { get; private set; }
/// <summary>
/// Предоставляет доступ к AppServiceProvider для приложения.
/// </summary>
public AppServiceProvider Services { get; private set; }
/// <summary>
/// Конструктор объекта приложения.
/// </summary>
public App()
{
// Глобальный обработчик неперехваченных исключений.
UnhandledException += Application_UnhandledException;
// Стандартная инициализация Silverlight
InitializeComponent();
// Инициализация телефона
InitializePhoneApplication();
// Инициализация XNA
InitializeXnaApplication();
// Отображение сведений о профиле графики во время отладки.
if (System.Diagnostics.Debugger.IsAttached)
{
// Отображение текущих счетчиков частоты смены кадров.
Application.Current.Host.Settings.EnableFrameRateCounter = true;
// Отображение областей приложения, перерисовываемых в каждом кадре.
//Application.Current.Host.Settings.EnableRedrawRegions = true;
// Включение режима визуализации анализа нерабочего кода
// для отображения областей страницы, переданных в GPU, с цветным наложением.
//Application.Current.Host.Settings.EnableCacheVisualization = true;
// Отключите обнаружение простоя приложения, установив для свойства UserIdleDetectionMode
// объекта PhoneApplicationService приложения значение Disabled.
// Внимание! Используйте только в режиме отладки. Приложение, в котором отключено обнаружение
бездействия пользователя, будет продолжать работать
// и потреблять энергию батареи, когда телефон не будет использоваться.
PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled;
}
}
// Код для выполнения при запуске приложения (например, из меню "Пуск")
// Этот код не будет выполняться при повторной активации приложения
private void Application_Launching(object sender, LaunchingEventArgs e)
{
}
// Код для выполнения при активации приложения (переводится в основной режим)
// Этот код не будет выполняться при первом запуске приложения
private void Application_Activated(object sender, ActivatedEventArgs e)
{
}
// Код для выполнения при деактивации приложения (отправляется в фоновый режим)
// Этот код не будет выполняться при закрытии приложения
private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
}
// Код для выполнения при закрытии приложения (например, при нажатии пользователем кнопки "Назад")
// Этот код не будет выполняться при деактивации приложения
private void Application_Closing(object sender, ClosingEventArgs e)
{
}
// Код для выполнения в случае ошибки навигации
private void RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
{
if (System.Diagnostics.Debugger.IsAttached)
{
// Ошибка навигации; перейти в отладчик
System.Diagnostics.Debugger.Break();
}
}
// Код для выполнения на необработанных исключениях
private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
{
if (System.Diagnostics.Debugger.IsAttached)
{
// Произошло необработанное исключение; перейти в отладчик
System.Diagnostics.Debugger.Break();
}
}
#region Инициализация приложения телефона
// Избегайте двойной инициализации
private bool phoneApplicationInitialized = false;
// Не добавляйте в этот метод дополнительный код
private void InitializePhoneApplication()
{
if (phoneApplicationInitialized)
return;
// Создайте кадр, но не задавайте для него значение RootVisual; это позволит
// экрану-заставке оставаться активным, пока приложение не будет готово для визуализации.
RootFrame = new PhoneApplicationFrame();
RootFrame.Navigated += CompleteInitializePhoneApplication;
// Обработка сбоев навигации
RootFrame.NavigationFailed += RootFrame_NavigationFailed;
// Убедитесь, что инициализация не выполняется повторно
phoneApplicationInitialized = true;
}
// Не добавляйте в этот метод дополнительный код
private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e)
{
// Задайте корневой визуальный элемент для визуализации приложения
if (RootVisual != RootFrame)
RootVisual = RootFrame;
// Удалите этот обработчик, т.к. он больше не нужен
RootFrame.Navigated -= CompleteInitializePhoneApplication;
}
#endregion
#region Инициализация приложения XNA
// Выполняет инициализацию типов XNA, необходимых для приложения.
private void InitializeXnaApplication()
{
// Создание поставщика услуг
Services = new AppServiceProvider();
// Добавить SharedGraphicsDeviceManager к службам в качестве IGraphicsDeviceService для приложения
foreach (object obj in ApplicationLifetimeObjects)
{
if (obj is IGraphicsDeviceService)
Services.AddService(typeof(IGraphicsDeviceService), obj);
}
// Создайте ContentManager для загрузки в приложение предварительно скомпилированных ресурсов
Content = new ContentManager(Services, "Content");
// Создайте GameTimer для получения XNA FrameworkDispatcher
FrameworkDispatcherTimer = new GameTimer();
FrameworkDispatcherTimer.FrameAction += FrameworkDispatcherFrameAction;
FrameworkDispatcherTimer.Start();
}
// Обработчик событий передает FrameworkDispatcher во все кадры.
// FrameworkDispatcher требуется для большинства событий XNA и
// некоторых функций, таких как воспроизведение SoundEffect.
private void FrameworkDispatcherFrameAction(object sender, EventArgs e)
{
FrameworkDispatcher.Update();
}
#endregion
}
}
Листинг
35.2.
Файл App.xaml.cs
Это всё тот же App.xaml.cs, которым мы пользовались ранее, однако, здесь производится инициализация механизмов XNA, создается ConetntManager для работы с XNA-контентом, создаётся таймер уровня приложения для FrameworkDispatcher.Update().

