В предыдущей заметке было рассказано о основных моментах связанных с разработкой игр для 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
Автор: dmandreev