Универсальная игра под Windows 8.1 RT и Windows Phone 8.1

Доброго дня, коллеги.Думаю, многие слышали о том, что Microsoft работает над созданием единой операционной системы под все платформы: мобильные, планшеты, десктопы, часы, холодильники.713cd9a848254360a6a871a9bb018eae.pngПричем движения в сторону объединения платформ они начинают делать уже сейчас. Если открыть Visual Studio 2013 Update 1, то в разделе разработки под Windows Store можно увидеть относительно новый пункт меню «Универсальные приложения». Сейчас со стороны Microsoft льётся активная реклама этих «универсальных приложений» в IT-уши, и я поддался этой рекламе. Но первый вопрос который я задал себе: «Почему только приложения? А не написать бы мне универсальную игру на C# и XAML». Если стало интересно что из этого получилось, жмите «Читать дальше».Сразу скажу, что к майкрософту я не имею отношения, да и программированием на C# и XAML занимаюсь в свободное от работы время. Итак, начнем.

ИНСТРУМЕНТЫДля того чтобы можно было писать такие вот универсальные приложения, нужна Visual Studio 2013 min c Update 1. По поводу младших версий не знаю. Также сказать, что осваивал программирование под Win8 платформу методом тыка + по книге Чарльза Петцольда «Программировании под Windows 8».ИДЕЯ Конечно самым простым вариантом было написать еще один «Flappy Bird», но от него уже тошнило даже меня. Идея появилась сама собой. Мы с женой, когда жили на окраине Минска и ехали на работу, то имели пол часа свободного времени которое дружно убивали на разные мобильные игры. Сначала у каждого были свои игры, но потом мы просто заразились одной игрой на двоих. Игра эта состояла из нескольких мини-игр, таких как «Алгебраические выражения», «Флаги стран»,»5 разных картинок» и т.д., и выигрывал тот, кто быстрее и правильнее нажмет на свою кнопку. Играли мы еще на моем стареньком Android-е, причем настолько увлеченно, что часто даже проезжали свою станцию. Потом оба обзавелись виндоусфонами, и прониклись к ним большой любовью. Но порывшись по местному маркету, пришло огорчение — таких игр под эту платформу просто не было, а те, что были представляли из себя жалкую пародию. Поэтому мне вдруг очень захотелось написать такую игру и под Windows Phone.ЦЕЛИ Целей было несколько:1. Очень хотелось снова играть с женой на двоих в игру на реакцию, но уже под Windows Phone-ом.2. Хотелось написать код так, чтобы читая его текла слеза умиления он отвечал требованиям паттерна MVVM, ведь в процессе я очень проникся идеей разделения кода модели от кода фьюшки.3. Давно хотелось написать что-то, что пусть и не будет великим, но приятным и во что будешь играть сам. Мой опыт разработки ограничивается работой в крупных компаниях (учетные системы на объектах розничной торговли, ERP-системы, банковское ПО). А там соответственно готовый продукт — это не результат энтузиазма, а уравнения в котором слагаемые это «ТЗ» и «дедлайн».РАЗРАБОТКА При разработке модели, можно сразу разделить два основных класса: Игроки и Мини-игры. Игроков может быть от двух до бесконечности, но учитывая размер экрана — ограничился шестью, по три с каждой стороны. Мини-игры тоже могут быть разные, с разным количеством заданий. Все это добро находится в управляющем классе «Игра». Для мини-игры был сделан родительский класс с базовым функционалом. Он много раз менялся, и как положительный результат этих изменений — некоторые из предков заданий стали занимать со ста до менее чем двадцати строк кода. Реализованы были такие мини-игры: • Внезапная картинка• Шесть разных картинок• Арифметика• Цвет и название• Обратный отсчет• Флаг страны• Столица страны и другие (10 различных мини игр)С кодированием модели каких-либо проблем не возникло, но вот разработка представления откровенно огорчила… Мои ожидания по поводу «здесь все прям как в WPF» разбились уже на элементарном: когда я захотел сделать псевдотридешную кнопку игрока, не смог найти радиальный градиент, который есть в WPF. Сначала подумал, что это ограничения дизайнера VS, но открыв Blend (ну мало ли) понял, что его нет нигде, пришлось довольствоваться линейным: 48e7febdd3934bfb8453cb0e0797dc15.png

Подобные мелочи хоть и встречались, но к каждой из них либо находился бубен, либо приходилось идти в ущерб функционалу.Несмотря на хронический недостаток свободного времени результат вырисовывался достаточно быстро. Буквально через пару недель я уже тестил игру под десктоп (Windows 8) и радовался жизни. Почему тестил только на десктопе? Да потому, что не мог понять, в чем может быть ошибка парсинга XAML кода для Windows Phone платформы:

c8aeaf64c17a49fcb337de6871278d4d.png

Одной рукой удаляя частями XAML-разметку, вторым глазом читал интернет и выяснил следующее: создание панелей

это Windows RT код, а для универсальных приложений нужно создавать уже

Но ведь этот код мне автоматически создал сам редактор Visual Studio 2013! Причем он это делает до сих пор и даже с update 3 ситуация не изменилась.После всего прочитанного в этой статье habrahabr.ru/company/microsoft/blog/218441/ предложение:

»…язык разметки XAML также был унифицирован между платформами»

осознавалось мной уже не просто с радостью (ведь это стало почти так, как и пишут), но и с некоторой досадой: жаль Visual Studio об этом еще не знает.Что касается общего кода — он действительно общий! В моем случае общим было все от модели до вьюшки (все кроме ресурсных файлов задающих размеры под определенную платформу).И теперь дело оставалось за реализацией платформенных фишек, типа интеграции в чудо-панель или поддержка закрепленного вида страницы.Чтобы пользователю удобно было воспринимать приложение как на десктопе, так и на телефоне сделал аналогичную чудо-панель и на телефоне. Выглядит это так: 0bc80e07f8be4f0289a2dd4009b29aae.png

И я увлекся общим кодом настолько, что даже меню сделал не просто хардкодное для каждой платформы, а формирующееся из общего списка объектов (элементов меню). А вот распихивались эти элементы меню уже под директивами, каждый под свою платформу, в свое меню. В Windows RT — это чудо-панель (под директивой #if WINDOWS_APP), а в Windows Phone — это обычная менюшка прикрепляемая сбоку (директивой #if WINDOWS_PHONE_APP), которая в Windows RT версии делалась Visible=false.Немного добавлю, что чудо-панель оказалась удобной штукой, но я к ней долго привыкал и хронически во всех приложениях искал вызов меню настроек какой-нибудь кнопкой расположенной в интерфейсе.Чтобы перемещаться по страницам, используется соответствующая визуальная кнопка со стрелочкой влево (<-). Там где этой стрелочки нет (например в процессе игры) использовал хардварные кнопки. На десктопе обрабатывается событие KeyPressed(Esc), а вот на телефоне, если нажать хардварную кнопку назад, то приложение схлопывалось и пользователь оказывался в главном плиточном меню. Все обработки события для версии 8 не помогали, в 8.1. Случайно наткнулся на событие, которое действительно начало вызываться при нажатии на хардварную кнопку назад:

using Windows.Phone.UI.Input; … HardwareButtons.BackPressed += HardwareButtons_BackPressed;

Для десктопа нужно было решить вопрос с закрепленным режимом, и опять же если раньше в 8 версии было только три варианта размещения окна: • приложение развернуто на весь экран (Full Screen); • приложение закреплено сбоку экрана (слева или cправа) (Snapped). Ширина приложения в таком режиме составляет 320 пикселов; • приложение работает совместно с другим закрепленным сбоку приложением и занимает все оставшееся пространство (Filled)То в 8.1 окно уже не цеплялось к этим вариантам, а размер окна можно стало менять в некоторых размещениях попиксельно. В идеале для каждого из режимов нужно создавать свой View, с измененным расположением элементов, размера шрифта и т.д. Я выбрал другой вариант — относительные координаты. Т.е. например поле с заданиями занимает 2/3 от длины экрана (сколько бы она не была в пикселях), а вот все компоненты с текстом запихнул в Parent-объект ViewBox. Данный объект автоматически масштабирует все что находится внутри него, в том числе и уменьшает размер шрифта в зависимости от своего размера, у всех Child-ах. Результат выглядит так:

a879ba3dd5da4dcaa26b5c9896468681.png

И пару слов об анимации: ведь так хочется, чтобы все также красиво выезжало и разворачивалось как и в самой операционной системе. Со стандартной анимацией проблем не было, она легко добавлялась и пряталась, но вот реализация собственных анимаций через Storyboard давало следующий эффект:

2f5cb58cc4dd40388e963aac714e2230.png

Т.е. изображения в процессе анимации сжимается так, что мягко говоря выглядит страшновато. Причем не важно, что это был за объект, результат одинаковый и для TextBlock и для Image. Насколько я могу догадываться, объект перед анимацией сжимается ооочень сильно, чтобы в процессе все выглядело плавно. Выхода из данной ситуации я к сожалению, не нашел, поэтому оставил все как есть. К тому же после того как анимация заканчивается, объект снова приобретает изначальное разрешение.По итогу нарисовал с десяток иконок разных монстриков (с маленькой «зелено-алой пасхалочкой» которая особенно порадует людей живущих в Беларуси), локализовал приложение на французский, английский языки с помощью друга Василия Лапицкого (за что ему большое спасибо), и на португальский, испанский и хинди с помощью Bing-транслита. Кстати был очень приятно удивлен на сколько просто делается локализация (в любой книге есть примеры, поэтому не буду на этом заострять внимания).

РЕЗУЛЬТАТЫ Результаты буду писать из целей:1. Теперь у нас с женой есть совместный тайм киллер не только на телефонах, но и на компьютере. Через него мы часто решаем кто пойдет в магазин или приготовит поесть.2. В целом, не смотря на некоторые мелочи, разрабатывать под платформу Windows 8.1 мне очень понравилось, но именно под 8.1, а не под 8! Хотя данная статья была немного акцентирована на имеющихся недоработках Microsoft, в целом простота разработки у меня часто вызывала простую программистскую радость. В универсальном проекте получилось 98% общего кода и лишь только 2% кода, заключенного в директивы — этот результат меня очень удивил, и на подобное я не рассчитывал, когда только брался за написание «универсальной игры».Вам не передать того восторга который я испытываю каждый раз, когда прихожу с работы домой и меняю Borland Builder 6.0 на VS2013, вижу свой код и горжусь им! И хоть понимаю, что совершенству кода нет предела, и что через некоторое время мне возможно опять что-то захочется переписать или улучшить. И пусть на работе днём мы с коллегами строим огромные небоскребы кода, вечером дОма я построил своё бунгало кода которое пусть и маленькое, но в нём так приятно каждый раз находиться. А как приятно достать телефон, поиграть со знакомым, тут же получить фитбэк от него, а потом сказать «да, это я написал».

ВМЕСТО ТЫСЯЧИ СЛОВ Это был хороший опыт, и сейчас у меня на свободное время приходится разработка еще одной игры, но уже на Unity.Что касается этой игры «Red Reactor», то она уже доступна как в Windows Store, так и в Windows Phone Store. Прямых ссылок приводить не буду, чтобы не сочли за рекламу.Получилось так, как я и хотел: интересно и весело. Мы периодически устраиваем турниры с друзьями, как по некоторым видам мини-игр, так и по всем. Кстати очень полезна игра будет и для детей, так как в ней развивается не только реакция и внимательность, но и арифметика + много географии.Игра абсолютно бесплатная и без внутренней рекламы, т.к. я правда программирую по вечерам для души, а не за деньги.

© Habrahabr.ru