Skip to content

Input management

Julien Pires edited this page Nov 8, 2013 · 9 revisions

HomeModules overview ▸ Input management

Introduction

Input management module has tools to work with input peripheral in an abstract way.

How it works

All functionalities are accessible via the InputManager class.

A common problem with input management is to support a wide range of peripheral without strong coupling in the code. One solution is to use virtual button mapped to real button. We can imagine that we have a virtual peripheral containing virtual button or axis. Each button/axis can be retrieve by it's name and can be linked to one or more "real" button coming from different source. Input module provides a way to do this.

AbstractButton is a struct used as a common interface to get the value of a button on a peripheral without have to know how the peripheral works.

In the next example, we will create a virtual Button which will be triggered by four different sources:

AbstractButton upKeyboard = new AbstractButton(Keys.Up); // Link to a keyboard key
AbstractButton upMouse = new AbstractButton(MouseButtons.Left); // Link to a mouse button
AbstractButton upGamepad = new AbstractButton(Buttons.DPadUp); // Link to a gamepad button
AbstractButton upTriggerGamepad = new AbstractButton(GamePadAnalogButtons.LeftTrigger); // Link to an analog gamepad button

Button forwardButton = new Button(){ Name = "Forward" };
forwardButton.AddButton(upKeyboard , 0);
forwardButton.AddButton(upMouse, 1);
forwardButton.AddButton(upGamepad, 2);
forwardButton.AddButton(upTriggerGamepad, 3);

Button class represents a virtual button. A virtual button has two states: up or down. You can also know if the button is pressed (up to down state) or released (down to up state). Now you just have to check the state of the virtual button regardless of which peripherals triggered it.

In the next example, we will create a virtual Axis:

AbstractButton upKeyboard = new AbstractButton(Keys.Up);
AbstractButton downKeyboard = new AbstractButton(Keys.Down);
AbstractButton leftThumbstick = new AbstractButton(GamePadAnalogButtons.LeftThumbStickY);

Axis vertical = new Axis(){ Name = "Vertical" };
vertical.AddButton(downKeyboard, upKeyboard, 0); // For digital button, defines a negative and positive trigger
vertical.AddButton(leftThumbstick, 1);

Axis class represents a virtual axis. A virtual axis only has a value. This value will be in a negative to positive range.

All virtual Button/Axis should be added to a VirtualInput in order to be up to date and easily retrievable. A VirtualInput is like a peripheral. VirtualInput are managed by the Player class, so you need to create a player first.

//Create a player
Player playerOne = inputManager.CreatePlayer(1);

/*
Create some buttons and axis
*/

VirtualInput virtualInput = playerOne.CreateContext("PlayerMovements"); // Get the virtual input from player
virtualInput.AddButton(forwardButton);
virtualInput.AddAxis(vertical);

/* Elsewhere in the game loop */
Button forwardButton = virtualInput.GetButton("Forward");
if(forwardButton.IsDown)
{
    // Do something
}

One VirtualInput represents one context in the Player class. A context is a way to associate a virtual input with a name. Making this possible allow to have different behaviour depending on the state of the game. For example, in a GTA-like, a player can walk or drive a car. When you walk the command are different than when you are driving. In this example, we just have to create two context: Walk and Drive. Each of these context will have it's own Button or Axis. When the player walk, we will looking for "Forward" or "Jump" button and when we will drive we will looking for "Accelerate" or "Brake" button.

// At the launch of the application, level or anything else
InputManager input = (IInputService)GameApplication.Services.GetService(typeof(IInputService)).Input;
PlayerInput player = input.CreatePlayer(0); // we create a player in the input manager
player.CreateContext("Drive");
player.CreateContext("Walk");

// Populates virtual input with Button/Axis

player.SetCurrentContext("Walk"); // Set Walk as the current context

You have to set a current context even if you can find it using GetContext method. If you don't set a current context no virtual input will be updated. Using SetCurrentContext allow you to find the current one faster via the CurrentContext property and doing this:

PlayerInput player = input.GetPlayer(0);

/* Elsewhere in the game loop */
player.GetAxis("Vertical");
player.GetButton("Forward");

GetAxis and GetButton of PlayerInput class target the current context. It's just a shortcut but avoid you to get the virtual input.