📜 ⬆️ ⬇️

Developing games for Windows 8 using MonoGame: touchscreen support

In the previous article it was told about the main points related to the development of games for Windows 8 and MonoGame. Despite the fact that the game is already running, it lacks the important functions that are necessary when implementing an application for Windows 8. This is touch support and a mandatory privacy policy screen.


Implementation of touch support


Windows 8 can run on the most diverse range of devices, including tablets that do not have a keyboard. Our game is a classic platformer, to control the character in the game only support for the gamepad and keyboard is implemented. To support devices without a keyboard but with a touch screen, code additions are needed.

The current implementation of MonoGame for Windows 8 allows you to poll the state of the screen sensor using the TouchPanel class from the Xna.Framework.Input.Touch. Supports gestures, and the combined interaction with the mouse. In the simplest case, in order to find out whether there is a click on the screen, it is enough to call the GetState() method which will return the list of points to which the touch is currently performed:
')
  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; } } 


The returned TouchLocation object contains data on the type, coordinates of the touch, its sequence number (up to five simultaneous points are supported as standard) and the force of pressing.

To support touches, we implement the standard approach adopted in many games - we will simply draw on the screen an image of the cursor keys and a jump button. Further it will be necessary only to calculate the coordinates of the touch areas, and poll them for the fact of pressing.

In the CastleX game itself, control event handling is implemented in two ways. The main menu handles events using the InputState class in each Update() method (before calling Draw ). At the same time, the InputState class remembers the previous state of keystrokes. Additionally, direct player status is used to control the player. These standard handlers are required to be modified.

The first thing we need to do is create images of the cursor keys and jump buttons. Using Paint.NET, two PNG files with transparency were created:



Next, these files must be placed in the Assets/GameContent . In principle, we do not even need to create an XNB file, the content subsystem in MonoGame can read PNG files directly.


As an example, the cursor keys will be displayed in the screen manager, and the Jump button only in the game screen.

Load the texture file in the LoadContent() method:

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


And display on the screen in the method Draw()

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



In this case, the alpha channel will be taken into account in the PNG file and, as a result, semi-transparent images of the cursor keys and buttons will be displayed on the screen:


But for now these are just static images and you need to handle push events in this area.

For this, a simple method will be used - just set the coordinates of the clicked area and we will check this coordinate for the state of the TouchLocationState.Moved

I would also like to keep the current infrastructure of event handling from the keyboard and gamepad implemented in the InputState class.

In the special method AddTouchKey(Keys key, Rectangle rect) coordinate associated with the key will be specified, and in addition to polling the keyboard status, the UpdateTouchKeys() method will also be called

  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; } 



This method polls all the clicked coordinates, and if they are included in the list of keypress areas associated with the keys, this button is added to the list of keystrokes for further use in the IsKeyDown() and IsKeyUp() methods IsKeyDown()

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



It should be noted that based on this code, pressing the screen has a higher priority than the keyboard. In principle, the changes made are enough for the game to work with the support of on-screen keys. Before standard polling, you only need to set the polling coordinates and associate them with the keys:

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



Add a privacy agreement to the game



One of the important conditions for passing certification when publishing applications is the existence of a privacy policy.


For applications on MonoGame, such a screen is implemented in a simple way; in the Init method of the basic class of the game, subscription to the events of the application properties call is made and the handler is set:

  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")); } 


You can download the original project with these changes at aka.ms/cgt2fr

Source: https://habr.com/ru/post/167815/


All Articles