Разработка игр для Windows 8 с использованием MonoGame: поддержка сенсорных экранов

В предыдущей заметке было рассказано о основных моментах связанных с разработкой игр для Windows 8 и MonoGame. Несмотря на то что игра уже запускается, в ней не хватает важных функций которые необходимы при реализации приложения для Windows 8. Это поддержка прикосновений и обязательный экран privacy policy.

Реализация поддержки прикосновений

ОС Windows 8 может запускаться на самом различном спектре устройств, в том числе на планшетах у которых отсутствует клавиатура. Наша игра является классическим платформером, для управления персонажем в игре реализована только поддержка геймпада и клавиатуры. Для поддержки устройств без клавиатуры но с сенсорным экраном необходимы дополнения в коде.

Текущая реализация MonoGame для Windows 8 позволяет опрашивать состояние сенсора экрана с помощью класса TouchPanel из области видимости Xna.Framework.Input.Touch. Поддерживаются жесты, и комбинированное взаимодействие с мышью. В простейшем случае, для того чтобы выяснить, есть ли нажатие на экран достаточно вызвать метод GetState() который вернет список точек к которым на данный момент осуществлено касание:

            foreach (TouchLocation location in TouchPanel.GetState())             {                 switch (location.State)                 {                     case TouchLocationState.Moved:                         // location.Position.X;                         // location.Position.Y;                         // location.Pressure                         // location.Id                         break;                     case TouchLocationState.Pressed:                         break;                     case TouchLocationState.Released:                         break;                     case TouchLocationState.Invalid:                         break;                 }             } 

Возвращаемый обьект TouchLocation содержит данные о типе, координатах касания, его порядковом номере (стандартно поддерживается до пяти одновременных точек) и силе нажатия.

Для поддержки касаний мы реализуем стандартный, принятый во многих играх подход – просто будем рисовать на экране изображение клавиш курсора и кнопку прыжка. Далее останется только вычислить координаты областей касаний, и опрашивать их на факт нажатия.

В самой игре CastleX обработка событий управления реализована двумя способами. Основное меню обратабывает события с помощью класса InputState в каждом методе Update() (перед вызовом Draw). При этом класс InputState помнит о предыдущем состоянии нажатия клавиш. Дополнительно, для управления игроком используется прямой опрос состояния клавиатуры. Эти стандартные обработчики требуется модифицировать.

Первое что нам нужно сделать это создать изображения курсорных клавиш и кнопки прыжка. Используя Paint.NET были созданы два PNG файла с прозрачностью:

Далее эти файлы нужно поместить в каталог Assets/GameContent. В принципе у нас даже нет необходимости создавать XNB файл, подсистема контента в MonoGame может прочитать файлы PNG напрямую.

В качестве примера клавиши курсора будут отображаться в менеджере экранов, а кнопка Jump только в экране игры.

Загружаем файл текстуры в методе LoadContent():

arrowkeys_texture = Content.Load<Texture2D>(@"transparent_arrow_keys"); 

И отображаем на экране в методе Draw()

              SpriteBatch.Begin();               SpriteBatch.Draw(arrowkeys_texture, drawPos, new Color(0, 0, 0));               SpriteBatch.End();  

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

Но пока это просто статичные изображения и необходимо обрабатывать события нажатия в этой области.

Для этого будет использоваться простой способ – просто зададим координаты области нажатия и будем проверять эту координату на состояние TouchLocationState.Moved

Так же хотелось бы сохранить текущую инфраструктуру обработки событий от клавиатуры и геймпада реализованную в классе InputState.

В специальном методе AddTouchKey(Keys key, Rectangle rect) будет задаваться координата ассоциированная с клавишей, и помимо опроса состояния клавиатуры так же будет вызван метод UpdateTouchKeys()

        internal bool UpdateTouchPos(Dictionary<Keys, bool> key_states )         {             bool touched = false;              foreach (Keys key in _touchKeys.Keys)                 key_states.Add(key,false);              foreach (TouchLocation location in TouchPanel.GetState())             {                 touched = true;                 foreach (var k in _touchKeys.Keys)                 {                     if (location.State == TouchLocationState.Moved)                     {                         if (_touchKeys[k].Contains((int)location.Position.X, (int)location.Position.Y))                         {                             key_states[k] = true;                         }                     }                 }             }              return touched;          } 

Этот метод опрашивает все нажатые координаты, и если они входят в список областей нажатия ассоциированных с клавишами, эта кнопка вносится в список нажатых клавиш для дальнейшего использования в методах IsKeyDown() и IsKeyUp()

        public bool IsKeyDown(Keys key)         {             if (touchKeys.ContainsKey(key) && isTouched)                 return touchKeys[key];             else                 return orig_key_state.IsKeyDown(key);         } 

Следует учитывать, что исходя из этого кода у нажатия на экран больший приоритет нежели у клавиатуры. В принципе проделанных изменений достаточно чтобы игра заработала с поддержкой экранных клавиш. Перед стандартным опросом надо только задать координаты опроса и ассоциировать их с клавишами:

     Input.AddTouchKey(Keys.Down, hitPosDown);      Input.AddTouchKey(Keys.Up, hitPosUp);      Input.AddTouchKey(Keys.Left, hitPosLeft);      Input.AddTouchKey(Keys.Right, hitPosRight);        Input.Update();  

Добавляем в игру соглашение о приватности

Одним из важных условий прохождения сертификации при публикации приложений является наличие соглашение о приватности (privacy policy).

Для приложений на MonoGame такой экран реализуется простым способом, в методе Init основгого класса игры производится подписка на события вызова свойств приложения и задается обработчик:

        protected override void Initialize()         {              base.Initialize();              SettingsPane.GetForCurrentView().CommandsRequested += PaneRequest;         }          void PaneRequest(SettingsPane sender, SettingsPaneCommandsRequestedEventArgs args)         {             UICommandInvokedHandler handler = new UICommandInvokedHandler(onPrivacyPolicyCommand);              var privPolicyCmd = new SettingsCommand("PrivacyPolicyId", "Privacy Policy", handler);              args.Request.ApplicationCommands.Add(privPolicyCmd);         }          void onPrivacyPolicyCommand(IUICommand command)         {             Launcher.LaunchUriAsync(new Uri("http://wincommunity.ru/baller/privacy.html"));         }  

Загрузить исходный проект этими изменениями вы можете по адресу aka.ms/cgt2fr

ссылка на оригинал статьи http://habrahabr.ru/company/microsoft/blog/167815/

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *