Разработка игры для Windows Phone 7.1-8.1

Для начала немного статистики.

Версии операционной системы Windows Phone 7 и 8

По данным статистики уже работающего приложения за последний месяц:

Статистика Windows phone 7

Видно, что 7-я версия занимает 30% от общего числа установок. Идея - разработать для обучения приложение, которое будет доступно и для 7.1+ версии. 

Решено сделать игру Точки. 

Вы начинаете игру с одной точки. На каждом уровне выбираете новую точку. Если выберете старую точку - проиграете. 

Полученная за день статистика разработанного и выложенного в магазин приложения:

Статистика распределения Windows Phone

Разработка

Важно отметить, что разработка приложений для Windows Phone 7 происходит исключительно в Visual Studio 2012. Верстка макетов в Blend 2012. При открытии проекта в 13 версии студии происходит принудительная конверстация проекта в новую версию и нет возможности публиковать приложение для старых версий.

Всего в игре 3 экрана: Стартовый (он же экран между уровнями), экран уровня и экран конца игры. В этом приложении в отличии от Судоку добавлен рейтинг игроков (количество точек). Рейтин реализован в виде API (без какой-либо серьезной защиты). Кроме того, что хочется посоревноваться в офисе - хочется также узнать кто сильнее в мире. Понятное дело что фотоаппарат решает, но без него интереснее. Правда!

Async

В Windows Phone 7 нет встроенной поддержки async await. Также нет некоторых элементов управления, упрощающих разработку. Вот мой список используемых packages из nuget.

<packages>
  <package id="Coding4Fun.Toolkit.Controls" version="2.0.7" targetFramework="wp71" />
  <package id="GoogleAnalyticsSDK" version="1.2.01" targetFramework="wp71" />
  <package id="Microsoft.Bcl" version="1.1.7" targetFramework="wp71" />
  <package id="Microsoft.Bcl.Async" version="1.0.16" targetFramework="wp71" />
  <package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="wp71" />
  <package id="Microsoft.Net.Http" version="2.1.10" targetFramework="wp71" />
  <package id="Newtonsoft.Json" version="5.0.7" targetFramework="wp71" />
  <package id="WPtoolkit" version="4.2013.08.16" targetFramework="wp71" />
</packages>

Для взаимодействия с API был разработан generic класс (httpclient), который кочует из проекта в проект. Примерный код класса представлен ниже.

using (HttpClientHandler handler = new HttpClientHandler())
{
    using (HttpClient httpClient = new HttpClient(handler))
    {
        using (HttpRequestMessage message = new HttpRequestMessage())
        {
            message.RequestUri = new Uri(url);
            message.Method = postData == null ? HttpMethod.Get : HttpMethod.Post;

            if (postData != null)
            {               
                message.Content = new StringContent(JsonConvert.SerializeObject(postData));
                message.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json; charset=utf-8");
            }

            HttpResponseMessage response = await httpClient.SendAsync(message).ConfigureAwait(false);
            string data = await response.Content.ReadAsStringAsync();
            return data;
        }
    }
}

Рисование точек происходит в объекте Canvas. Каждая точка это Button со стилем. Генерация точек и цветов абсолютно случайная (иногда попадается 4-5 точек одного цвета очень близко, приходится ориентироваться по относительному положених их друг друга. Код генерации показан ниже. Кроме того, учитываются пересечения точек. Генерация происходит до тех пор, пока не найдется такое местое, где не будет пересечения с другими точками (или кончится цикл, тогда будет в случайном месте)

DotInfo dot = new DotInfo();
dot.Color = Colors[Rand.Next(Colors.Count)];

int testX = 0, testY = 0;
bool testOk = true;

for (int i = 0; i < 10000; i++)
{
    testX = Rand.Next(Width - ButtonSize);
    testY = Rand.Next(Heigth - ButtonSize);

    testOk = true;

    foreach (DotInfo dotInfo in _dots)
    {
        Rectangle intersect =
            Rectangle.Intersect(new Rectangle(dotInfo.X, dotInfo.Y, ButtonSize, ButtonSize),
                new Rectangle(testX, testY, ButtonSize, ButtonSize));

        if (intersect != Rectangle.Empty)
            testOk = false;
    }

    if (testOk)
    {
        dot.X = testX;
        dot.Y = testY;
        break;
    }
}

if (!testOk)
{
    dot.X = Rand.Next(Width - ButtonSize);
    dot.Y = Rand.Next(Heigth - ButtonSize);
}

Имя игрока запрашивается элементом управления от издателя Coding4Fun. Кстати очень интересные контролы, советую посмотреть. (Coding4Fun Toolkit)

InputPrompt input = new InputPrompt();
input.Completed += UserNameInputOK;
input.Title = "Введите имя";
input.Value = UserSettings.Value.UserName;
if (string.IsNullOrEmpty(input.Value))
    input.Value = "Игрок " + randName.Next(Int32.MaxValue / 2);


input.Show();

Взаимодействие с настройками пользователей и сохраняемыми данными реализовано по рекомендации "Introduction and best practices for IsolatedStorageSettings" от Nokia. Решение оказалось интересным и очень удобным. http://developer.nokia.com/community/wiki/Introduction_and_best_practices_for_IsolatedStorageSettings

Публикация в обновленный магазин

Практически сразу после конференции Build обновился магазин приложений (как на клиенсткой части, так и для разработчиков)

Магазин Windows Phone

Добавился пункт об изменениях в новой версии (чтобы не изменять описание самого приложение) и не захламлять его.

описание приложения

 Добавилось резервирование имени приложения для Windows Phone приложений (в довесок в Windows Store)

резервирование имени

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

имя в приложения

В общей сложности на написание этого приложения + небольшой серверной части ушло 20 часов. Стоит заметить, что публикация приложения в магазин стала космически быстрой (всего 30 минут). Дополнительные ошибки получил при интеграции async-await в приложение Windows Phone 7.5. Падала странная ошибка FileNotFound. Думаю, что решилось недавним обновление BCL библиотек Microsoft.

P.S. мой рекорд 24 точки, а у вас?

Рекорд точек

Буду рад комментариям, предложениям и хорошим оценкам в магазине.

 

Комментарии

comments powered by Disqus