Quantcast
Channel: directxtk Wiki Rss Feed
Viewing all articles
Browse latest Browse all 874

Updated Wiki: GamePad

$
0
0
This is a helper for simplified access to gamepad controllers through the XInput API modeled after the XNA GamePad class.

Header

#include <GamePad.h>

Initialization

GamePad is a simple singleton.

std::unique_ptr<GamePad> gamePad( new GamePad );
For exception safety, it is recommended you make use of the C++ RAII pattern and use a std::unique_ptr.

Basic Use

auto state = gamePad->GetState( 0 );

if ( state.IsConnected() )
{
    if ( state.IsAPressed() )
        // Do action for button A being downif ( state.y )
        // Do action for button Y being downif ( state.IsDPadLeftPressed() )
        // Do action for DPAD Left being downif ( state.dpad.up || state.dpad.down || state.dpad.left || state.dpad.right )
        // Do action based on any DPAD changefloat posx = state.thumbSticks.leftX;
    float posy = state.thumbSticks.leftY;
        // These values are normalized to -1 to 1float throttle = state.triggers.right;
        // This value is normalized 0 -> 1
}

Dead Zones

GamePad implements the same dead zone scheme as XNA used.
  • DEAD_ZONE_INDEPENDENT_AXES which is the default
  • DEAD_ZONE_CIRCULAR which provides a deadzone for the combined X/Y axes
  • DEAD_ZONE_NONE which provides 'raw' scaled information to allow the application to implement dead zones
See Shawn's blog for details.
http://blogs.msdn.com/b/shawnhar/archive/2007/03/28/gamepads-suck.aspx

Device Capabilities

The GamePad class provides a simplified model for the device capabilties.

auto caps = gamePad->GetCapabilities( 0 );
if ( caps.IsConnected() )
{
    if ( caps.gamepadType == GamePad::FLIGHT_STICK )
        // Take special interpretation based on a flight stick
}

Note that much of the information reported in XINPUT_CAPABILITIES is omitted. This is because much of it is unreliable (see below), but also because the actionable information is enitrely captured by the gamepadType subtype.

Button State Tracker

A common pattern for gamepads is to trigger an event when a button is pressed or released, but that you don't want to trigger every single frame if the button is held down for more than a single frame. This helper class simplifies this.

std::unique_ptr<GamePad::ButtonStateTracker> tracker( new  GamePad::ButtonStateTracker );

...

auto state = gamdPad->GetState( 0 );
if ( state.IsConnected() )
{
    tracker->Update( state );

    if ( tracker->a == GamePad::ButtonStateTracker::PRESSED )
        // Take an action when Button A is first pressed, but don't do it again until// the button is released and then pressed again
}

Each button is reported by the tracker with a state UP, HELD, PRESSED, or RELEASED.

Threading model

The GamePad class provides no special synchronziation above the underlying API. XInput on Windows is thread-safe through a internal global lock, so performance is best when only a single thread accesses the controller.

Remark

The GamePad object and the underlying system APIs are polling based. Typically the controller is read once per render frame, which means that low frame-rate can result in missing user input.

Platform Notes

Windows

For the Windows platform, the GamePad class ensures that attempts to locate unconnected controllers do not happen too frequently to avoid a potential performance issue. When built for Windows 8.0 or later, it makes use of XInput 1.4. When built for down-level support, it makes use of XInput 9.1.0 which avoids the need for any dependancy on the legacy DirectSetup.

Note that subtype capabilities information is somewhat unrealiable down-level depending on your exact mix of device and driver, and in some cases is hard-coded. It is reliable on Windows 8.0 or later.

Xbox One

On Xbox One, this class is implemented using the Windows.Xbox.Input interfaces rather than XInput. It is abstracted to return the same structures. Note that currently only the GAMEPAD type is reported for Xbox One.

The playerIndex mapping is not correlated directly with a user as it is on Xbox 360 or Windows, and is assigned 'upon arrival'. To determine the actual user for a given gamepad, you should use the controller ID reported as part of the Capabilities.

auto caps = gamePad->GetCapabilities( playerIndex );
if ( caps.IsConnected() )
{
    try
    {
        auto ctrl = Controller::GetControllerById( caps.id );
        if ( ctrl )
        {
            User^ user = ctrl->User;
            // user is the user associated with the controller, if any
        }
    }
    catch ( Platform::Exception ^ e )
    {
        // error handling, likely the controller has been removed//  since the caps were obtained
    }
}

Windows Phone

The GamePad object can be created and used on Windows Phone, but it will always report no devices connected. The original XNA 4 API would report the Windows Phone hardware back button as Buttons.Back, but this implementation does not do this as the information about the hardware button is communicated through ICoreWindows messages.

Further Reading

http://blogs.msdn.com/b/chuckw/archive/2012/04/26/xinput-and-windows-8-consumer-preview.aspx
http://blogs.msdn.com/b/chuckw/archive/2012/05/03/xinput-and-xaudio2.aspx

Viewing all articles
Browse latest Browse all 874

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>