- НОВОСТИ
- Microsoft добавит поддержку Windows.Gaming.Input API для Chromium-браузеров в Windows 10 и Windows 10X
- Windows. Gaming. Input Namespace
- Classes
- Structs
- Interfaces
- Enums
- Remarks
- Input for games
- Gaming input devices
- Gamepads
- Arcade sticks
- Racing wheels
- Flight sticks
- Raw game controllers
- UI navigation controllers
- Headsets
- Users
- Gamepad Class
- Definition
- Windows 10 requirements
- Examples
- Remarks
- Supported Devices
- Version history
- Properties
- Methods
- Events
- Способы ввода данных в играх Input practices for games
- Выбор класса устройств ввода Choosing an input device class
- Отслеживание подключенных контроллеров Keeping track of connected controllers
- Отслеживание пользователей и их устройств Tracking users and their devices
- Определение положений кнопки Detecting button transitions
- Определение сложных схем положений кнопок Detecting complex button arrangements
- Получение состояния аккумулятора Get the state of the battery
НОВОСТИ
Microsoft добавит поддержку Windows.Gaming.Input API для Chromium-браузеров в Windows 10 и Windows 10X
Windows version | SDK version | Value added |
---|---|---|
1607 | 14393 | GetButtonLabel |
1703 | 15063 | FromGameController |
1703 | 15063 | TryGetBatteryReport |
Properties
The list of all connected gamepads.
The audio headset attached to the gamepad.
Gets a value that indicates the wireless state of the gamepad.
The user associated with the gamepad.
Describes the gamepad motor speed.
Methods
Returns the given game controller as a gamepad.
Retrieves the button label for the specified button.
Gets a snapshot of the gamepad state.
Gets information about the gamepad’s current battery state.
Events
Signals when a new gamepad is connected.
Signals when a gamepad is disconnected.
Signals when a headset is attached to the gamepad.
Signals when a headset is disconnected from the gamepad.
Signals when the user associated with the gamepad has changed.
Способы ввода данных в играх Input practices for games
В этом разделе описываются шаблоны и методы эффективного использования устройств ввода в играх универсальная платформа Windows (UWP). This topic describes patterns and techniques for effectively using input devices in Universal Windows Platform (UWP) games.
Прочитав этот раздел, вы узнаете следующее: By reading this topic, you’ll learn:
- как отслеживать игроков, а также используемые ими устройства ввода и навигации; how to track players and which input and navigation devices they’re currently using
- как определять положения кнопок (из нажатого в отпущенное, из отпущенного в нажатое); how to detect button transitions (pressed-to-released, released-to-pressed)
- как определять сложные схемы положений кнопок с помощью одной проверки. how to detect complex button arrangements with a single test
Выбор класса устройств ввода Choosing an input device class
Существует множество различных API-интерфейсов ввода, таких как ArcadeStick, FlightStick и Gamepad. There are many different types of input APIs available to you, such as ArcadeStick, FlightStick, and Gamepad. Как выбрать оптимальный API-интерфейс для своей игры? How do you decide which API to use for your game?
Выбирайте любой API-интерфейс, который максимально подходит для ввода данных в вашей игре. You should choose whichever API gives you the most appropriate input for your game. Например, если вы разрабатываете игру на двухмерной платформе, можно просто использовать класс Gamepad и не задействовать дополнительные функциональные возможности, предоставляемые другими классами. For example, if you’re making a 2D platform game, you can probably just use the Gamepad class and not bother with the extra functionality available via other classes. В этом случае игра будет поддерживать только геймпады. Единообразный интерфейс обеспечит совместимость со множеством различных геймпадов, поэтому вам не придется писать дополнительный код. This would restrict the game to supporting gamepads only and provide a consistent interface that will work across many different gamepads with no need for additional code.
С другой стороны, для сложных игр-симуляторов, где пользователи управляют самолетами или гоночными машинами, потребуется перечислить все объекты RawGameController. Этот базовый план необходим для поддержки нишевых устройств, распространенных среди геймеров-энтузиастов. Такие устройства могут быть оснащены отдельными педалями или рукоятками управления двигателем, рассчитанными на одного игрока. On the other hand, for complex flight and racing simulations, you might want to enumerate all of the RawGameController objects as a baseline to make sure they support any niche device that enthusiast players might have, including devices such as separate pedals or throttle that are still used by a single player.
С помощью методов класса ввода FromGameController, таких как Gamepad.FromGameController, можно проверить, насколько тщательно контролируется каждое устройство. From there, you can use an input class’s FromGameController method, such as Gamepad.FromGameController, to see if each device has a more curated view. Например, если устройство также относится к классу Gamepad, возможно, потребуется изменить пользовательский интерфейс сопоставления кнопок и предоставить игроку выбор из нескольких практичных стандартных сопоставлений. For example, if the device is also a Gamepad, then you might want to adjust the button mapping UI to reflect that, and provide some sensible default button mappings to choose from. (Обратите внимание на различие: если используется только RawGameController, игроку придется вручную настраивать элементы управления геймпада.) (This is in contrast to requiring the player to manually configure the gamepad inputs if you’re only using RawGameController.)
Кроме того, можно посмотреть код поставщика (VID) и код продукта (PID) в классе RawGameController (с помощью методов HardwareVendorId и HardwareProductId соответственно) и создать рекомендуемые сопоставления кнопок для популярных устройств. При этом игра будет по-прежнему совместима с еще неизвестными будущими устройствами, так как игрок сможет настроить сопоставления вручную. Alternatively, you can look at the vendor ID (VID) and product ID (PID) of a RawGameController (using HardwareVendorId and HardwareProductId, respectively) and provide suggested button mappings for popular devices while still remaining compatible with unknown devices that come out in the future via manual mappings by the player.
Отслеживание подключенных контроллеров Keeping track of connected controllers
Хотя каждый тип контроллера включает список подключенных контроллеров (например, Gamepad.Gamepads), желательно вести свой собственный список контроллеров. While each controller type includes a list of connected controllers (such as Gamepad.Gamepads), it is a good idea to maintain your own list of controllers. Подробнее см. в разделе Список геймпадов (в статье о каждом типе контроллеров есть раздел с аналогичным названием). See The gamepads list for more information (each controller type has a similarly named section on its own topic).
Однако что произойдет, если пользователь отключит свой контроллер или подключит новый? However, what happens when the player unplugs their controller, or plugs in a new one? Эти события необходимо обрабатывать и соответствующим образом обновлять список. You need to handle these events, and update your list accordingly. Подробнее см. в разделе Добавление и удаление геймпадов (снова-таки, в статье о каждом типе контроллеров есть раздел с аналогичным названием). See Adding and removing gamepads for more information (again, each controller type has a similarly named section on its own topic).
Поскольку события добавления и удаления вызываются асинхронно, при работе со списком контроллеров есть возможность получить неверные результаты. Because the added and removed events are raised asynchronously, you could get incorrect results when dealing with your list of controllers. Поэтому всякий раз, когда вы обращаетесь к своему списку контроллеров, вы должны установить для него блокировку, чтобы к нему одновременно мог обращаться только один поток. Therefore, anytime you access your list of controllers, you should put a lock around it so that only one thread can access it at a time. Это можно сделать с помощью параллельной среды выполнения, а именно класса critical_section, который находится в
Еще один момент, который нужно учитывать, — это то, что список подключенных контроллеров изначально будет пустым, и его заполнение займет одну-две секунды. Another thing to think about is that the list of connected controllers will initially be empty, and takes a second or two to populate. Поэтому, если вы только назначаете текущий геймпад в методе запуска, он будет иметь значение null! So if you only assign the current gamepad in the start method, it will be null!
Чтобы это исправить, нужно предусмотреть метод, который «обновляет» главный геймпад (в игре с одним игроком; многопользовательские игры требуют более сложных решений). To rectify this, you should have a method that «refreshes» the main gamepad (in a single-player game; multiplayer games will require more sophisticated solutions). Этот метод затем следует вызывать в обработчиках событий добавления и удаления контроллеров или же в методе обновления. You should then call this method in both your controller added and controller removed event handlers, or in your update method.
Следующий метод просто возвращает первый геймпад в списке (или nullptr, если список пустой). The following method simply returns the first gamepad in the list (or nullptr if the list is empty). Затем просто нужно не забывать делать проверку на предмет nullptr всякий раз, когда вы делаете что-либо с этим контроллером. Then you just need to remember to check for nullptr anytime you do anything with the controller. Блокировать ли игровой процесс при отсутствии подключенного контроллера (например, приостанавливать игру) или оставлять его продолжаться без ввода — решать вам. It’s up to you whether you want to block gameplay when there’s no controller connected (for example, by pausing the game) or simply have gameplay continue, while ignoring input.
Чтобы продемонстрировать все это вместе, вот пример обработки ввода с помощью геймпада: Putting it all together, here is an example of how to handle input from a gamepad:
Отслеживание пользователей и их устройств Tracking users and their devices
Все устройства ввода связаны с классом User, чтобы удостоверение пользователя можно было сопоставить с игровыми моментами, достижениями, изменениями параметров и другими действиями. All input devices are associated with a User so that their identity can be linked to their gameplay, achievements, settings changes, and other activities. Пользователи могут входить в устройство ввода и выходить из него в любое время. Часто случается, что после выхода первого пользователя в устройство ввода, подключенное к системе, входит другой пользователь. При входе или выходе пользователя возникает событие IGameController.UserChanged. Users can sign in or sign out at will, and it’s common for a different user to sign in on an input device that remains connected to the system after the previous user has signed out. When a user signs in or out, the IGameController.UserChanged event is raised. Вы можете зарегистрировать обработчик событий для этого события, чтобы отслеживать игроков и используемые устройства. You can register an event handler for this event to keep track of players and the devices they’re using.
Удостоверение пользователя — это также способ, с помощью которого устройство ввода связано с соответствующим контроллером навигации пользовательского интерфейса. User identity is also the way that an input device is associated with its corresponding UI navigation controller.
В связи с этим необходимо отслеживать вводимые пользователем данные и сопоставлять их с помощью свойства User в классе устройств (это свойство наследуется у интерфейса IGameController). For these reasons, player input should be tracked and correlated with the User property of the device class (inherited from the IGameController interface).
В примере усергамепадпаирингувп показано, как можно отследить пользователей и устройства, которые они используют. The UserGamepadPairingUWP sample demonstrates how you can keep track of users and the devices they’re using.
Определение положений кнопки Detecting button transitions
Иногда бывает необходимо узнать, когда пользователь сначала нажимает или отпускает кнопку, а именно, в какой момент состояние кнопки переходит из отпущенного состояния в нажатое или наоборот. Sometimes you want to know when a button is first pressed or released; that is, precisely when the button state transitions from released to pressed or from pressed to released. Чтобы определить это, необходимо знать данные ввода, считанные с устройства ранее, и сравнить с ними текущие показания, чтобы понять, какие изменения произошли. To determine this, you need to remember the previous device reading and compare the current reading against it to see what’s changed.
В следующем примере кода представлен базовый подход к запоминанию предыдущих считанных показаний. Пример основан на геймпадах, однако для аркадного джойстика, гоночного руля и других устройств ввода действуют такие же принципы. The following example demonstrates a basic approach for remembering the previous reading; gamepads are shown here, but the principles are the same for arcade stick, racing wheel, and the other input device types.
Сначала Game::Loop перемещает существующее значение newReading (данные ввода, считанные с геймпада во время предыдущей итерации цикла) в oldReading , а затем заполняет newReading новым считанным с геймпада значением для текущей итерации. Before doing anything else, Game::Loop moves the existing value of newReading (the gamepad reading from the previous loop iteration) into oldReading , then fills newReading with a fresh gamepad reading for the current iteration. На основании полученной информации вы можете определять положения кнопок. This gives you the information you need to detect button transitions.
В следующем примере кода представлен базовый подход к обнаружению изменений состояния кнопки: The following example demonstrates a basic approach for detecting button transitions:
Эти две функции сначала наследуют логическое состояние выбранной кнопки из newReading и oldReading , а затем выполняют бинарную логику, чтобы определить, произошло ли целевое изменение состояния кнопки. These two functions first derive the Boolean state of the button selection from newReading and oldReading , then perform Boolean logic to determine whether the target transition has occurred. Эти функции возвращают значение true, только если новые считанные данные содержат целевое состояние (кнопка нажата или отпущена соответственно) и ранее считанные данные не содержат целевое состояние; в противном случае они возвращают значение false. These functions return true only if the new reading contains the target state (pressed or released, respectively) and the old reading does not also contain the target state; otherwise, they return false.
Определение сложных схем положений кнопок Detecting complex button arrangements
Каждая кнопка на устройстве ввода предоставляет цифровые данные, указывающие на ее состояние: нажата (down) или отпущена (up). Each button of an input device provides a digital reading that indicates whether it’s pressed (down) or released (up). В целях обеспечения эффективности эти показания кнопок не указываются в виде отдельных логических значений. Вместо этого все они упаковываются в битовые поля, представляемые соответствующими перечислениями, например GamepadButtons (в зависимости от устройства). For efficiency, button readings aren’t represented as individual boolean values; instead, they’re all packed into bitfields represented by device-specific enumerations such as GamepadButtons. Для считывания данных с конкретных кнопок используется побитовая маскировка, позволяющая изолировать нужные значения. To read specific buttons, bitwise masking is used to isolate the values that you’re interested in. Кнопка нажата, когда установлен соответствующий бит (состояние down); в противном случае кнопка отпущена (состояние up). A button is pressed (down) when its corresponding bit is set; otherwise, it’s released (up).
Вспомним, как определяется положение отдельных кнопок (нажата или отпущена). Пример основан на геймпадах, однако для аркадного джойстика, гоночного руля и других устройств ввода действуют такие же принципы. Recall how single buttons are determined to be pressed or released; gamepads are shown here, but the principles are the same for arcade stick, racing wheel, and the other input device types.
Как видно, определить состояние одной кнопки просто, но иногда нужно определить состояние нескольких кнопок или положение кнопок в наборе—некоторые кнопки могут быть нажаты, а другие отпущены. As you can see, determining the state of a single button is straight-forward, but sometimes you might want to determine whether multiple buttons are pressed or released, or if a set of buttons are arranged in a particular way—some pressed, some not. Проверку состояния нескольких кнопок выполнить сложнее, чем проверку состояния одной кнопки—особенно когда существует вероятность, что состояние кнопок разное—однако для этих проверок существует простое правило, которое одинаково успешно применяется и к одной кнопке, и к нескольким. Testing multiple buttons is more complex than testing single buttons—especially with the potential of mixed button state—but there’s a simple formula for these tests that applies to single and multiple button tests alike.
В следующем примере показано, как определить, нажаты ли обе кнопки геймпада «A» и «B»: The following example determines whether gamepad buttons A and B are both pressed:
В следующем примере показано, как определить, отпущены ли обе кнопки геймпада «A» и «B»: The following example determines whether gamepad buttons A and B are both released:
В следующем примере показано, как определить, нажата ли кнопка геймпада «A» одновременно с отпущенной кнопкой «B»: The following example determines whether gamepad button A is pressed while button B is released:
Правило, объединяющее все эти пять примеров кода, заключается в том, что расположение проверяемых кнопок, задается выражением в левой части оператора равенства, тогда как кнопки, состояние которых следует учитывать, выбираются с помощью выражения маскировки в правой части. The formula that all five of these examples have in common is that the arrangement of buttons to be tested for is specified by the expression on the left-hand side of the equality operator while the buttons to be considered are selected by the masking expression on the right-hand side.
В следующем примере были внесены изменения по сравнению с предыдущим, поэтому правило показано более наглядно: The following example demonstrates this formula more clearly by rewriting the previous example:
Это правило можно применять для проверки любого количества кнопок с любой схемой состояний. This formula can be applied to test any number of buttons in any arrangement of their states.
Получение состояния аккумулятора Get the state of the battery
Для любого игрового устройства управления, реализующего интерфейс IGameControllerBatteryInfo, можно вызвать метод TryGetBatteryReport в экземпляре устройства управления, чтобы получить объект BatteryReport, который предоставляет информацию об аккумуляторе в устройстве. For any game controller that implements the IGameControllerBatteryInfo interface, you can call TryGetBatteryReport on the controller instance to get a BatteryReport object that provides information about the battery in the controller. Можно получить такие свойства, как скорость зарядки (ChargeRateInMilliwatts), предполагаемую энергоемкость нового аккумулятора (DesignCapacityInMilliwattHours) и энергоемкость текущего аккумулятора при полной зарядке (FullChargeCapacityInMilliwattHours). You can get properties like the rate that the battery is charging (ChargeRateInMilliwatts), the estimated energy capacity of a new battery (DesignCapacityInMilliwattHours), and the fully-charged energy capacity of the current battery (FullChargeCapacityInMilliwattHours).
Для игровых устройств управления, поддерживающих подробную отчетность по аккумуляторам, можно получить эту и другую информацию об аккумуляторе, как описано в разделе Получение сведений об аккумуляторе. For game controllers that support detailed battery reporting, you can get this and more information about the battery, as detailed in Get battery information. Тем не менее большинство игровых устройств управления не поддерживают такой уровень отчетности по аккумуляторам, т. к. в них используются недорогие аппаратные элементы. However, most game controllers don’t support that level of battery reporting, and instead use low-cost hardware. Для таких контроллеров необходимо помнить следующее: For these controllers, you’ll need to keep the following considerations in mind:
ChargeRateInMilliwatts и DesignCapacityInMilliwattHours всегда будут иметь значение NULL. ChargeRateInMilliwatts and DesignCapacityInMilliwattHours will always be NULL.
Процент аккумулятора можно получить, выполнив вычисление ремаинингкапаЦитинмилливатсаурс / фуллчаржекапаЦитинмилливатсаурс. You can get the battery percentage by calculating RemainingCapacityInMilliwattHours / FullChargeCapacityInMilliwattHours. Значения этих свойств следует игнорировать и использовать только вычисленный процент. You should ignore the values of these properties and only deal with the calculated percentage.
Процент в предыдущем пункте всегда будет иметь одно из следующих значений: The percentage from the previous bullet point will always be one of the following:
- 100% (полностью заряжено) 100% (Full)
- 70% (средний уровень) 70% (Medium)
- 40% (низкий уровень) 40% (Low)
- 10% (критический уровень) 10% (Critical)
Если ваш код выполняет какое-либо действие (например, рисует пользовательский интерфейс) на основании оставшегося уровня заряда аккумулятора, следите за тем, чтобы он соответствовал значениям выше. If your code performs some action (like drawing UI) based on the percentage of battery life remaining, make sure that it conforms to the values above. Например, если вы хотите предупреждать игрока о низком заряде аккумулятора в контроллере, делайте это тогда, когда заряд опустится до 10%. For example, if you want to warn the player when the controller’s battery is low, do so when it reaches 10%.