Опубликован: 14.08.2012 | Уровень: специалист | Доступ: платный
Самостоятельная работа 28:

Совместное использование Silverlight и XNA

Страница MainPage.xaml – это обычная стартовая страница Silverlight-приложения, рис. 35.3.

Страница MainPage.xaml

Рис. 35.3. Страница MainPage.xaml

Здесь располагается кнопка "Изменить на страницу игры". Правильнее будет подписать её как "Перейти на страницу игры", так как именно эту функцию она и выполняет. В листинге 35.3 приведен её код.

<phone:PhoneApplicationPage 
    x:Class="P28_1.MainPage"
    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:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="800"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="False">

    <!--LayoutRoot представляет корневую сетку, где размещается все содержимое страницы-->
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!--TitlePanel содержит имя приложения и заголовок страницы-->
        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock x:Name="ApplicationTitle" Text="МОЕ ПРИЛОЖЕНИЕ" 
            Style="{StaticResource PhoneTextNormalStyle}"/>
            <TextBlock x:Name="PageTitle" Text="имя страницы" Margin="9,-7,0,0" 
            Style="{StaticResource PhoneTextTitle1Style}"/>
        </StackPanel>

        <!--ContentPanel — поместите здесь дополнительное содержимое-->
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            
            <!--Создание одной кнопки для перехода ко второй странице, визуализация которой выполнена XNA Framework-->
            <Button Height="100" Content="Изменить на страницу игры" Click="Button_Click" />
            
        </Grid>
    </Grid>
 
    <!--Пример кода, иллюстрирующий использование ApplicationBar-->
    <!--<phone:PhoneApplicationPage.ApplicationBar>
        <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
            <shell:ApplicationBarIconButton IconUri="/Images/appbar_button1.png" Text="Кнопка 1"/>
            <shell:ApplicationBarIconButton IconUri="/Images/appbar_button2.png" Text="Кнопка 2"/>
            <shell:ApplicationBar.MenuItems>
                <shell:ApplicationBarMenuItem Text="Элемент меню 1"/>
                <shell:ApplicationBarMenuItem Text="Элемент меню 2"/>
            </shell:ApplicationBar.MenuItems>
        </shell:ApplicationBar>
    </phone:PhoneApplicationPage.ApplicationBar>-->

</phone:PhoneApplicationPage>
Листинг 35.3. Файл MainPage.xaml

Страница стандартна, она по умолчанию содержит настройку, скрывающую системные значки, что приводит к отображению страницы на полный экран. В её CS-файле, листинг 35.4., содержится обработчик нажатия на кнопку, открывающий страницу GamePage.

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.Shapes;
using Microsoft.Phone.Controls;

namespace P28_1
{
    public partial class MainPage : PhoneApplicationPage
    {
        // Конструктор
        public MainPage()
        {
            InitializeComponent();
        }

        // Простая кнопка Щелкните обработчик событий, чтобы перейти на вторую страницу
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            NavigationService.Navigate(new Uri("/GamePage.xaml", UriKind.Relative));
        }
    }
}
Листинг 35.4. Файл MainPage.xaml.cs

Собственно говоря, мы можем пользоваться всем арсеналом инструментов и приёмов Silverlight, работая со страницей MainPage и с другими Silverlight—страницами проекта.

XAML-код страницы GamePage, листинг 35.5., задаёт лишь свойства PhoneApplicationPage. В частности, по умолчанию игровой экран будет выводиться в портретной ориентации.

<phone:PhoneApplicationPage 
    x:Class="P28_1.GamePage"
    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:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    mc:Ignorable="d" d:DesignHeight="800" d:DesignWidth="480"
    shell:SystemTray.IsVisible="False">
    
    <!--Содержимое XAML не требуется, поскольку полная визуализация страницы выполнена XNA Framework-->

</phone:PhoneApplicationPage>
Листинг 35.5. Файл GamePage.xaml

Другой нагрузки он, в шаблоне проекта, не несет, так как вся работа по созданию игры ведется в файле GamePage.xaml.cs. Если мы соберемся использовать Silverlight-элементы на XNA-странице, нам придется описывать их визуализацию в GamePage.xaml.cs. В этом файле нас ждёт самое интересное – реализация механизмов XNA.

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.Navigation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace P28_1
{
    public partial class GamePage : PhoneApplicationPage
    {
        ContentManager contentManager;
        GameTimer timer;
        SpriteBatch spriteBatch;

        public GamePage()
        {
            InitializeComponent();

            // Получить диспетчер содержимого из приложения
            contentManager = (Application.Current as App).Content;

            // Создайте таймер для этой страницы
            timer = new GameTimer();
            timer.UpdateInterval = TimeSpan.FromTicks(333333);
            timer.Update += OnUpdate;
            timer.Draw += OnDraw;
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            // В графическом устройстве включите визуализацию XNA для режима совместного использования
            SharedGraphicsDeviceManager.Current.GraphicsDevice.SetSharingMode(true);

            // Создание нового SpriteBatch, который может использоваться для рисования текстур.
            spriteBatch = new SpriteBatch(SharedGraphicsDeviceManager.Current.GraphicsDevice);

            // TODO: загрузите сюда содержимое игры с помощью this.content

            // Запуск таймера
            timer.Start();

            base.OnNavigatedTo(e);
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            // Остановка таймера
            timer.Stop();

            // В графическом устройстве выключите визуализацию XNA для режима совместного использования
            SharedGraphicsDeviceManager.Current.GraphicsDevice.SetSharingMode(false);

            base.OnNavigatedFrom(e);
        }

        /// <summary>
        /// Позволяет странице выполнять логику, такую как обновление окружения,
        /// поиск конфликтов, сбор входных данных и воспроизведение звука.
        /// </summary>
        private void OnUpdate(object sender, GameTimerEventArgs e)
        {
            // TODO: добавьте здесь логику обновления
        }

        /// <summary>
        /// Разрешает автоматическую прорисовку страницы.
        /// </summary>
        private void OnDraw(object sender, GameTimerEventArgs e)
        {
            SharedGraphicsDeviceManager.Current.GraphicsDevice.Clear(Color.CornflowerBlue);

            // TODO: добавьте здесь свой код прорисовки
        }
    }
}
Листинг 35.6. Файл GamePage.xaml.cs

В конструкторе (GamePage) мы получаем диспетчер содержимого, что позволяет нам работать с контентом, кроме того, в классе определено несколько переменных. Это – вышеупомянутый ContentManager, это timerобъект типа GameTimer, на основе которого на странице работают методы, аналогичные методам Update и Draw в обычных XNA-проектах. Это хорошо знакомый вам по XNA-проектам объект типа SpriteBatch, который используется для визуализации двумерных графических объектов.

В конструкторе, кроме того, мы создаём игровой таймер, назначаем интервал срабатывания таймера, соответствующий времени обновления экрана (как в XNA-проектах, другими словами) и определяем обработчики для его событий Update и Draw – то есть – готовим всё для работы игрового цикла XNA.

В методе OnNavigatedTo, выполняющемся при переходе на страницу, мы запускаем XNA-визуализацию, создаём новый SpriteBatch, и, кроме того, здесь мы будем загружать ресурсы игры. Здесь же мы запускаем таймер.

Когда мы уходим со страницы, игровой таймер останавливается.

Метод OnUpdate – это аналог метода Update из XNA. Здесь мы будем реализовывать игровую логику. Метод OnDraw – аналог метода Draw. Он предназначен для отрисовки игровых объектов. По умолчанию здесь присутствует лишь команда очистки экрана.

Посмотрим теперь, как пользоваться вышеописанными механизмами на практике.

Гулич Анна
Гулич Анна
Невозможно пройти тесты, в окне с вопросами пусто
Сашечка Огнев
Сашечка Огнев
Россия, Красноярский край
Андрей Корягин
Андрей Корягин
Россия, Пенза, Вазерская средняя школа, 2001