How to Poll For Controller Input In UWP App

2019-09-20 02:44发布

问题:

I'm unsure about the best practice for obtaining and updating input received from a controller monitored using the GamePad class in UWP.

I've seen a couple of examples of people using Dispatch Timers and async loops inside the GamePadAdded event. In Win32 applications, I would have handled input in the WinMain update/message loop, but in UWP apps I don't know of anything similar.

Is there a loop in UWP apps that input should be collected/handled like in Win32 apps? What is the recommended protocol for polling for input from a input device (nominally a Xbox One controller)?

I'm happy to read more about UWP app development but I'm unsure of any guides that reference something like this.

Edit: It would be productive if, instead of downvoting and moving on, you shared thoughts on why this question deserved a downvote.

回答1:

I've seen a couple of examples of people using Dispatch Timers and async loops inside the GamePadAdded event

This is the right way in UWP app to read Gamepad data. A little suggestion is, move the loop reading part on UI thread if you need to update UI frequently. See the solution in this blog

Is there a loop in UWP apps that input should be collected/handled like in Win32 apps

You may make a wrapper with custom event, see the open source implementation: XBoxGamepad

public class XBoxGamepad
{
    private List<Gamepad> _controllers = new List<Gamepad>();
    private bool _running = true;

    Task backgroundWorkTask;

    public event EventHandler<GamepadButtons> OnXBoxGamepadButtonPressA;
    //omitted......

    public XBoxGamepad()
    {
        Gamepad.GamepadAdded += Gamepad_GamepadAdded;
        Gamepad.GamepadRemoved += Gamepad_GamepadRemoved;
        backgroundWorkTask = Task.Run(() => PollGamepad());
    }

    //omitted......

    private void Start()
    {
        _running = true;
    }

    public void Stop()
    {
        _running = false;
    }

    public async Task PollGamepad()
    {
        while (true)
        {
            if (_running)
            {
                foreach (Gamepad controller in _controllers)
                {
                    if (controller.GetCurrentReading().Buttons == GamepadButtons.A)
                    {
                        OnXBoxGamepadButtonPressA(controller, controller.GetCurrentReading().Buttons);
                    }
                    //omitted......
                }
            }
            await Task.Delay(50);
        }
    }

    private void Gamepad_GamepadRemoved(object sender, Gamepad e)
    {
        _controllers.Remove(e);
    }

    private void Gamepad_GamepadAdded(object sender, Gamepad e)
    {
        _controllers.Add(e);
    }
    }