Думаю, многие слышали о том, что Microsoft работает над созданием единой операционной системы под все платформы: мобильные, планшеты, десктопы, часы, холодильники.
Причем движения в сторону объединения платформ они начинают делать уже сейчас. Если открыть Visual Studio 2013 Update 1, то в разделе разработки под Windows Store можно увидеть относительно новый пункт меню «Универсальные приложения». А не написать бы мне универсальную игру на C# и XAML».
Сразу скажу, что к Microsoft я не имею отношения, да и программированием на C# и XAML занимаюсь в свободное от работы время. Итак, начнем.
ИНСТРУМЕНТЫ
Для того чтобы можно было писать такие вот универсальные приложения, нужна Visual Studio 2013 min c Update 1. По поводу младших версий не знаю. Также сказать, что осваивал программирование под Win8 платформу методом тыка + по книге Чарльза Петцольда «Программировании под Windows 8».
ИДЕЯ
Конечно самым простым вариантом было написать еще один «Flappy Bird», но от него уже тошнило даже меня. Идея появилась сама собой. Мы с женой, когда жили на окраине Минска и ехали на работу, то имели пол часа свободного времени которое дружно убивали на разные мобильные игры. Сначала у каждого были свои игры, но потом мы просто заразились одной игрой на двоих. Игра эта состояла из нескольких мини-игр, таких как «Алгебраические выражения», «Флаги стран», «5 разных картинок» и т.д., и выигрывал тот, кто быстрее и правильнее нажмет на свою кнопку. Играли мы еще на моем стареньком Android-е, причем настолько увлеченно, что часто даже проезжали свою станцию. Потом оба обзавелись виндоусфонами, и прониклись к ним большой любовью. Но порывшись по местному маркету, пришло огорчение — таких игр под эту платформу просто не было, а те, что были представляли из себя жалкую пародию. Поэтому мне вдруг очень захотелось написать такую игру и под Windows Phone.
ЦЕЛИ
Целей было несколько:
- Очень хотелось снова играть с женой на двоих в игру на реакцию но уже под Windows Phone-ом.
- Хотелось написать код так, чтобы читая его текла слеза умиления он отвечал требованиям паттерна MVVM, ведь в процессе я очень проникся идеей разделения кода модели от кода фьюшки.
- Давно хотелось написать что-то, что пусть и не будет великим, но приятным и во что будешь играть сам. Мой опыт разработки ограничивается работой в крупных компаниях (учетные системы на объектах розничной торговли, ERP-системы, банковское ПО). А там соответственно готовый продукт — это не результат энтузиазма, а уравнения в котором слагаемые это «ТЗ» и «дедлайн».
РАЗРАБОТКА
При разработке модели, можно сразу разделить два основных класса: Игроки и Мини-игры. Игроков может быть от двух до бесконечности, но учитывая размер экрана – ограничился шестью, по три с каждой стороны. Мини-игры тоже могут быть разные, с разным количеством заданий. Все это добро находится в управляющем классе «Игра». Для мини-игры был сделан родительский класс с базовым функционалом. Он много раз менялся, и как положительный результат этих изменений – некоторые из предков заданий стали занимать со ста до менее чем двадцати строк кода. Реализованы были такие мини-игры:
- Внезапная картинка
- Шесть разных картинок
- Арифметика
- Цвет и название
- Обратный отсчет
- Флаг страны
- Столица страны и другие (10 различных мини игр)
С кодированием модели каких-либо проблем не возникло, но вот разработка представления откровенно огорчила… Мои ожидания по поводу «здесь все прям как в WPF» разбились уже на элементарном: когда я захотел сделать псевдотридешную кнопку игрока, не смог найти радиальный градиент, который есть в WPF. Сначала подумал, что это ограничения дизайнера VS, но открыв Blend (ну мало ли) понял, что его нет нигде, пришлось довольствоваться линейным:
Подобные мелочи хоть и встречались, но к каждой из них либо находился бубен, либо приходилось идти в ущерб функционалу.
Несмотря на хронический недостаток свободного времени результат вырисовывался достаточно быстро. Буквально через пару недель я уже тестил игру под десктоп (Windows 8) и радовался жизни. Почему тестил только на десктопе? Да потому, что не мог понять, в чем может быть ошибка парсинга XAML кода для Windows Phone платформы:
Одной рукой удаляя частями XAML-разметку, вторым глазом читал интернет и выяснил следующее: создание панелей
<Page.BottomAppBar> <AppBar />< /Page.BottomAppBar>
это Windows RT код, а для универсальных приложений нужно создавать уже
<Page.BottomAppBar> <CommandBar />< /Page.BottomAppBar>
Но ведь этот код мне автоматически создал сам редактор Visual Studio 2013! Причем он это делает до сих пор и даже с update 3 ситуация не изменилась.
После всего прочитанного в этой статье habrahabr.ru/company/microsoft/blog/218441/ предложение:
«…язык разметки XAML также был унифицирован между платформами»
осознавалось мной уже не просто с радостью (ведь это стало почти так, как и пишут), но и с некоторой досадой: жаль Visual Studio об этом еще не знает.
Что касается общего кода – он действительно общий! В моем случае общим было все от модели до вьюшки (все кроме ресурсных файлов задающих размеры под определенную платформу).
И теперь дело оставалось за реализацией платформенных фишек, типа интеграции в чудо-панель или поддержка закрепленного вида страницы.
Чтобы пользователю удобно было воспринимать приложение как на десктопе, так и на телефоне сделал аналогичную чудо-панель и на телефоне. Выглядит это так:
Увеличить
И я увлекся общим кодом настолько, что даже меню сделал не просто хардкодное для каждой платформы, а формирующееся из общего списка объектов (элементов меню). А вот распихивались эти элементы меню уже под директивами, каждый под свою платформу, в свое меню. В Windows RT – это чудо-панель (под директивой #if WINDOWS_APP), а в Windows Phone – это обычная менюшка прикрепляемая сбоку (директивой #if WINDOWS_PHONE_APP), которая в Windows RT версии делалась Visible=false.
- приложение развернуто на весь экран (Full Screen);
- приложение закреплено сбоку экрана (слева или cправа) (Snapped). Ширина приложения в таком режиме составляет 320 пикселов;
- приложение работает совместно с другим закрепленным сбоку приложением и занимает все оставшееся пространство (Filled)
То в 8.1 окно уже не цеплялось к этим вариантам, а размер окна можно стало менять в некоторых размещениях попиксельно. В идеале для каждого из режимов нужно создавать свой View, с измененным расположением элементов, размера шрифта и т.д. Я выбрал другой вариант – относительные координаты. Т.е. например поле с заданиями занимает 2/3 от длины экрана (сколько бы она не была в пикселях), а вот все компоненты с текстом запихнул в Parent-объект ViewBox. Данный объект автоматически масштабирует все что находится внутри него, в том числе и уменьшает размер шрифта в зависимости от своего размера, у всех Child-ах. Результат выглядит так:
Увеличить
И пару слов об анимации: ведь так хочется, чтобы все также красиво выезжало и разворачивалось как и в самой операционной системе. Со стандартной анимацией проблем не было, она легко добавлялась и пряталась, но вот реализация собственных анимаций через Storyboard давало следующий эффект:
Увеличить
Т.е. изображения в процессе анимации сжимается так, что мягко говоря выглядит страшновато. Причем не важно, что это был за объект, результат одинаковый и для TextBlock и для Image. Насколько я могу догадываться, объект перед анимацией сжимается ооочень сильно, чтобы в процессе все выглядело плавно. Выхода из данной ситуации я к сожалению, не нашел, поэтому оставил все как есть. К тому же после того как анимация заканчивается, объект снова приобретает изначальное разрешение.
РЕЗУЛЬТАТЫ
Результаты буду писать из целей:
- Теперь у нас с женой есть совместный тайм киллер не только на телефонах, но и на компьютере. Через него мы часто решаем кто пойдет в магазин или приготовит поесть.
- В целом, не смотря на некоторые мелочи, разрабатывать под платформу Windows 8.1 мне очень понравилось, но именно под 8.1, а не под 8! Хотя данная статья была немного акцентирована на имеющихся недоработках Microsoft, в целом простота разработки у меня часто вызывала простую программистскую радость. В универсальном проекте получилось 98% общего кода и лишь только 2% кода, заключенного в директивы – этот результат меня очень удивил, и на подобное я не рассчитывал, когда только брался за написание «универсальной игры».
ВМЕСТО ТЫСЯЧИ СЛОВ
Что касается этой игры «Red Reactor», то она уже доступна как в Windows Store, так и в Windows Phone Store. Прямых ссылок приводить не буду, чтобы не сочли за рекламу.