Программируем на Monogame. Часть 4. Windows Store приложения Monogame+Xaml

В прошлых статьях мы уже рассматривали проекты Monogame для Windows Store, теперь мы рассмотрим новый тип проекта – Windows Store Xaml проект. Такой тип проектов позволяет задействовать мощнейшую технологию – Xaml. Использование Xaml позволит нам в полной мере использовать возможности Windows Store приложений.

Хочу заметить, что использование Xaml, безусловно, не является необходимым. Мы можем использовать проекты на Monogame так же, как мы раньше использовали XNA, то есть приложение всегда содержало один экран (с точки зрения кода), на котором мы могли рисовать все, что нам захочется. С другой стороны в XNA у нас никогда не было возможности использовать уже существующие в Windows контролы, такие как кнопки, списки, меню и т.д. (да, это не совсем правда, мы могли использовать такие элементы управления, но все это по большому счету было «костылями», а по настоящему использовать связку Silverlight+XNA у большинства разработчиков не было времени, так как это связка по сути стала устаревшей уже где-то через пол года после ее появления).

Замечение:
Хочу обратить внимание на то, что использование Xaml, к сожалению, затруднит портирование приложения на те платформы, на которых он не поддерживается.

Начнем с создания нового проекта Windows Store Game (Xaml).

Видно, что в этом проекте уже больше файлов. Более того, есть папки обычные для Windows Store приложений – Assets (содержит различные иконки для приложения) и Common (содержит стандратные стили).

Основной файл Xaml приложений, как всегда, App.xaml. Если посмотреть на исходный код его cs сосотавляющей, то мы увидем следующее:

using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.UI.Xaml;

// The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=234227

namespace XamlTest
{
    /// <summary>
    /// Provides application-specific behavior to supplement the default Application class.
    /// </summary>
    sealed partial class App : Application
    {
        /// <summary>
        /// Initializes the singleton application object.  This is the first line of authored code
        /// executed, and as such is the logical equivalent of main() or WinMain().
        /// </summary>
        public App()
        {
            InitializeComponent();
            Suspending += OnSuspending;
        }

        /// <summary>
        /// Invoked when the application is launched normally by the end user.  Other entry points
        /// will be used when the application is launched to open a specific file, to display
        /// search results, and so forth.
        /// </summary>
        /// <param name="args">Details about the launch request and process.</param>
        protected override void OnLaunched(LaunchActivatedEventArgs args)
        {
            var gamePage = Window.Current.Content as GamePage;

            // Do not repeat app initialization when the Window already has content,
            // just ensure that the window is active
            if (gamePage == null)
            {
                // Create a main GamePage
                gamePage = new GamePage(args.Arguments);

                if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
                {
                    // TODO: Load state from previously suspended application
                }

                // Place the GamePage in the current Window
                Window.Current.Content = gamePage;
            }

            // Ensure the current window is active
            Window.Current.Activate();
        }

        /// <summary>
        /// Invoked when application execution is being suspended.  Application state is saved
        /// without knowing whether the application will be terminated or resumed with the contents
        /// of memory still intact.
        /// </summary>
        /// <param name="sender">The source of the suspend request.</param>
        /// <param name="e">Details about the suspend request.</param>
        private void OnSuspending(object sender, SuspendingEventArgs e)
        {
            var deferral = e.SuspendingOperation.GetDeferral();

            // TODO: Save application state and stop any background activity

            deferral.Complete();
        }
    }
}

Видно, что за нас уже проделана некоторая работа. В частности метод OnSuspending понадобится нам для сохранения состояния игры, когда пользователь свернет ее. А метод OnLaunched обрабатывает включение приложения и в реализации по умолчанию он устанавливает в качестве текущей страницы страницу GamePage.

На самом деле в этом месте кроется один неприятный момент: при таком подходе (установке страницы в качестве содержимого окна Window.Current.Content = gamePage) у нас пропадает возможность выполнять навигацию между страницами. И эту проблему мы решим, но позже.

Пока же нас устраивает текущая реализация.

Обратимся к странице GamePage.xaml.

<SwapChainBackgroundPanel
    x:Class="XamlTest.GamePage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:XamlTest"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid>
    </Grid>

</SwapChainBackgroundPanel>

Тут можно заметить, что вместо привычой страницы используется SwapChainBackgroundPanel. Эта панель используется для работы с такими API как OpenGL или DirectX. Поскольку это, по сути, обычная страница с Xaml разметкой, то мы может создавать сколь угодно сложный пользовательский интерфейс, выполнять связывание и т.д.

Например, если создать кнопку на странице, то она будет отображаться поверх MonoGame содержимого.

<SwapChainBackgroundPanel
    x:Class="XamlTest.GamePage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:XamlTest"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid>
        <Button Content="THIS IS THE TEST BUTTON" HorizontalAlignment="Center"/>
    </Grid>

</SwapChainBackgroundPanel>

Кнопка будет нажиматься и реагировать на события.

Больше ничего интересного в разметке нет, посмотрим на cs файл.

using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using MonoGame.Framework;

namespace XamlTest
{
    /// <summary>
    /// The root page used to display the game.
    /// </summary>
    public sealed partial class GamePage : SwapChainBackgroundPanel
    {
        readonly Game1 _game;

        public GamePage(string launchArguments)
        {
            this.InitializeComponent();

            // Create the game.
            _game = XamlGame<Game1>.Create(launchArguments, Window.Current.CoreWindow, this);
        }
    }
}

Тут создается объект игры (экземпляр Game1). Пока у нас есть всего один экран нас такой код устроит. Дальше, видимо, придется с ним разбираться, а пока нам важно лишь то, что Game1 создается и все его методы вызываются в правильном порядке и с нужной частотой.

Пока все, в следующий раз мы создадим приложение из нескольких страниц с навигацией, а дальше будем комбинировать Xaml контролы с MonoGame содержимым игры.

Реклама
Запись опубликована в рубрике Компьютерная графика с метками , , , , , , . Добавьте в закладки постоянную ссылку.

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s