飛行桿Flight stick

此頁面說明使用 Windows.Gaming.Input.ArcadeStickarcadestick 的 Xbox One 飛行桿程式認證基本知識,以及通用 Windows 平台 (UWP) 的相關 API。This page describes the basics of programming for Xbox One-certified flight sticks using Windows.Gaming.Input.FlightStick and related APIs for the Universal Windows Platform (UWP).

閱讀此頁面,即可了解:By reading this page, you'll learn:

  • 如何收集所連接飛行桿及其使用者的清單how to gather a list of connected flight sticks and their users
  • 如何偵測已新增或移除飛行桿how to detect that a flight stick has been added or removed
  • 如何讀取來自一或多個飛行桿的輸入how to read input from one or more flight sticks
  • 飛行搖桿如何當成 UI 瀏覽裝置使用how flight sticks behave as UI navigation devices

概觀Overview

飛行桿是遊戲輸入裝置,價值在於重現飛機或太空船駕駛艙中的飛行桿體驗。Flight sticks are gaming input devices that are valued for reproducing the feel of flight sticks that would be found in a plane or spaceship's cockpit. 它們是快速且準確控制飛行的完美輸入裝置。They're the perfect input device for quick and accurate control of flight. 在 Windows 10 和 Xbox One UWP 應用程式中,飛行桿是由 Windows.Gaming.Input 命名空間所支援。Flight sticks are supported in Windows 10 and Xbox One UWP apps by the Windows.Gaming.Input namespace.

Xbox One 飛行桿配備下列控制項︰Xbox One flight sticks are equipped with the following controls:

  • 可翻滾、俯仰及偏擺的可彎式類比搖桿A twistable analog joystick capable of roll, pitch, and yaw
  • 一個類比節流閥An analog throttle
  • 兩個開火按鈕Two fire buttons
  • 一個數位控制帽切換裝置An 8-way digital hat switch
  • 檢視功能表按鈕View and Menu buttons

注意

檢視功能表按鈕用來支援 UI 瀏覽,而非遊戲命令,因此無法直接存取為搖桿按鈕。The View and Menu buttons are used to support UI navigation, not gameplay commands, and therefore can't be readily accessed as joystick buttons.

UI 瀏覽UI navigation

為了減輕支援不同輸入裝置進行使用者介面瀏覽的負擔,以及鼓勵遊戲與裝置之間的一致性,大部分「實體」__ 輸入裝置同時會當成稱為 UI 瀏覽控制器的「邏輯」__ 輸入裝置使用。In order to ease the burden of supporting the different input devices for user interface navigation and to encourage consistency between games and devices, most physical input devices simultaneously act as separate logical input devices called UI navigation controllers. UI 瀏覽控制器提供跨輸入裝置之 UI 瀏覽命令的通用詞彙。The UI navigation controller provides a common vocabulary for UI navigation commands across input devices.

飛行桿是UI 瀏覽控制器,會將瀏覽命令的必要設定對應到搖桿及ViewMenuFirePrimary,和FireSecondary按鈕。As a UI navigation controller, a flight stick maps the required set of navigation commands to the joystick and View, Menu, FirePrimary, and FireSecondary buttons.

導覽命令Navigation command 飛行桿輸入Flight stick input
UpUp 搖桿向上Joystick up
DownDown 搖桿向下Joystick down
LeftLeft 搖桿向左Joystick left
RightRight 搖桿向右Joystick right
檢視View View按鈕View button
功能表Menu 功能表 按鈕Menu button
接受Accept FirePrimary 按鈕FirePrimary button
取消Cancel FireSecondary 按鈕FireSecondary button

飛行桿不會對應瀏覽命令的任何選用設定Flight sticks don't map any of the optional set of navigation commands.

偵測和追蹤飛行桿Detect and track flight sticks

使用與遊戲台相同的方式偵測及追蹤飛行桿的運作,但 FlightStick 類別除外,而不是 Gamepad 類別。Detecting and tracking flight sticks works in exactly the same way as it does for gamepads, except with the FlightStick class instead of the Gamepad class. 如需詳細資訊,請參閱遊戲台與震動See Gamepad and vibration for more information.

讀取飛行桿Reading the flight stick

在您找出感興趣的飛行桿之後,即可收集其輸入。After you identify the flight stick that you're interested in, you're ready to gather input from it. 不過,飛行桿不是透過引發事件來溝通狀態變更,這與您可能習慣使用的一些其他類型的輸入不同。However, unlike some other kinds of input that you might be used to, flight sticks don't communicate state-change by raising events. 相反的,您可以進行_輪詢_來定期讀取其目前狀態。Instead, you take regular readings of their current state by polling them.

輪詢飛行桿Polling the flight stick

輪詢可在精確的時間點擷取飛行桿的快照。Polling captures a snapshot of the flight stick at a precise point in time. 這種輸入收集方式適用於大部分遊戲,因為其邏輯一般是以決定性迴圈執行,而不是透過事件驅動This approach to input gathering is a good fit for most games because their logic typically runs in a deterministic loop rather than being event-driven. 從一次全部收集的輸入來解譯遊戲命令,一般也比從不同時間收集的許多單一輸入來解譯遊戲命令更為簡單。It's also typically simpler to interpret game commands from input gathered all at once than it is from many single inputs gathered over time.

您可輪詢飛行桿,透過呼叫FlightStick.GetCurrentReadingYou poll a flight stick by calling FlightStick.GetCurrentReading. 這項功能會傳回FlightStickReading包含飛行桿的狀態。This function returns a FlightStickReading that contains the state of the flight stick.

下列範例會對飛行桿的目前狀態進行輪詢。The following example polls a flight stick for its current state:

auto flightStick = myFlightSticks->GetAt(0);
FlightStickReading reading = flightStick->GetCurrentReading();

除了飛行桿狀態之外,每次讀取都會包含精確指出狀態擷取時間的時間戳記。In addition to the flight stick state, each reading includes a timestamp that indicates precisely when the state was retrieved. 時間戳記適用於與先前讀取的計時或遊戲模擬的計時建立關聯。The timestamp is useful for relating to the timing of previous readings or to the timing of the game simulation.

讀取搖桿和節流閥輸入Reading the joystick and throttle input

搖桿提供 X 和 Y 軸中介於 -1.0 與 1.0 之間的類比讀數(分別是翻滾、俯仰、偏擺)。The joystick provides an analog reading between -1.0 and 1.0 in the X, Y, and Z axes (roll, pitch, and yaw, respectively). 若是翻滾,-1.0 的值對應到最左邊的搖桿位置;1.0 的值對應到最右邊的搖桿位置。For roll, a value of -1.0 corresponds to the left-most joystick position, while a value of 1.0 corresponds to the right-most position. 若是俯仰,-1.0 的值對應到最底端的搖桿位置;1.0 的值對應到最頂端的搖桿位置。For pitch, a value of -1.0 corresponds to the bottom-most joystick position, while a value of 1.0 corresponds to the top-most position. 若是偏擺,-1.0 值對應最逆時鐘、彎曲的位置,而 1.0 對應最順時針方向的位置。For yaw, a value of -1.0 corresponds to the most counterclockwise, twisted position, while a value of 1.0 corresponds to the most clockwise position.

在所有軸中,搖桿處於中心位置時,值大約會是 0.0,但其精確值通常會不同,即使在後續讀取時也是一樣In all axes, the value is approximately 0.0 when the joystick is in the center position, but it's normal for the precise value to vary, even between subsequent readings. 本節稍後會討論如何減少這項差異。Strategies for mitigating this variation are discussed later in this section.

搖桿的值讀取自FlightStickReading.Roll屬性、繞 X 軸旋轉的值讀取自FlightStickReading.Pitch屬性和繞 Y 軸旋轉的值讀取自FlightStickReading.Yaw屬性︰The value of the joystick's roll is read from the FlightStickReading.Roll property, the value of the pitch is read from the FlightStickReading.Pitch property, and the value of the yaw is read from the FlightStickReading.Yaw property:

// Each variable will contain a value between -1.0 and 1.0.
float roll = reading.Roll;
float pitch = reading.Pitch;
float yaw = reading.Yaw;

讀取搖桿值時,如果搖桿靜止在中心位置,您會注意到搖桿值不會確實地產生中性讀數 0.0;相反地,每次移動搖桿並回到中心位置時,它們都會產生接近 0.0 的不同值。When reading the joystick values, you'll notice that they don't reliably produce a neutral reading of 0.0 when the joystick is at rest in the center position; instead, they'll produce different values near 0.0 each time the joystick is moved and returned to the center position. 若要減少這些變化,您可以實作小型「靜止區域」__,這是指接近理想中心位置的可忽略值範圍。To mitigate these variations, you can implement a small deadzone, which is a range of values near the ideal center position that are ignored.

實作靜止區域的一種方法是判定搖桿與中心的距離,若讀數比您選擇的距離值更接近中心則予以忽略。One way to implement a deadzone is to determine how far the joystick has moved from the center, and ignore readings that are nearer than some distance you choose. 只要使用畢式定理,就可以約略計算出距離;因為搖桿讀數基本上是極性 (非平面) 值,所以距離不是確切值。You can compute the distance roughly—it's not exact because joystick readings are essentially polar, not planar, values—just by using the Pythagorean theorem. 所產生的會是一個放射狀靜止區域。This produces a radial deadzone.

下列範例會使用畢式定理示範基本放射狀靜止區域。The following example demonstrates a basic radial deadzone using the Pythagorean theorem:

// Choose a deadzone. Readings inside this radius are ignored.
const float deadzoneRadius = 0.1f;
const float deadzoneSquared = deadzoneRadius * deadzoneRadius;

// Pythagorean theorem: For a right triangle, hypotenuse^2 = (opposite side)^2 + (adjacent side)^2
float oppositeSquared = pitch * pitch;
float adjacentSquared = roll * roll;

// Accept and process input if true; otherwise, reject and ignore it.
if ((oppositeSquared + adjacentSquared) < deadzoneSquared)
{
    // Input accepted, process it.
}

讀取按鈕與控制帽切換裝置Reading the buttons and hat switch

飛行桿的兩個開火按鈕都各自提供數位讀取來指出按下(向下)或放開(向上)。Each of the flight stick's two fire buttons provides a digital reading that indicates whether it's pressed (down) or released (up). 為了更有效率,按鈕讀取並非作為個別布林值呈現,而是壓縮成由 FlightStickButtons 列舉所呈現的單一位元欄位。For efficiency, button readings aren't represented as individual boolean values—instead, they're all packed into a single bitfield that's represented by the FlightStickButtons enumeration. 此外,控制帽切換裝置提供壓縮成由GameControllerSwitchPosition列舉所呈現的單一位元欄位。In addition, the 8-way hat switch provides a direction packed into a single bitfield that's represented by the GameControllerSwitchPosition enumeration.

注意

飛行桿配備用於 UI 瀏覽的其他按鈕,例如 ViewMenu按鈕。Flight sticks are equipped with additional buttons used for UI navigation such as the View and Menu buttons. 這些按鈕不是 FlightStickButtons 列舉的一部分,而且只能將飛行桿當成 UI 瀏覽裝置存取來進行讀取。These buttons are not part of the FlightStickButtons enumeration and can only be read by accessing the flight stick as a UI navigation device. 如需詳細資訊,請參閱 UI 瀏覽控制器For more information, see UI navigation controller.

按鈕值讀取自FlightStickReading.Buttons屬性。The button values are read from the FlightStickReading.Buttons property. 因為此屬性是位元欄位,所以使用位元遮罩來隔離感興趣按鈕的值。Because this property is a bitfield, bitwise masking is used to isolate the value of the button that you're interested in. 設定對應位元時,即按下 (向下) 按鈕;否則為放開 (向上)。The button is pressed (down) when the corresponding bit is set; otherwise, it's released (up).

下列範例會判斷是否按下FirePrimary按鈕。The following example determines whether the FirePrimary button is pressed:

if (FlightStickButtons::FirePrimary == (reading.Buttons & FlightStickButtons::FirePrimary))
{
    // FirePrimary is pressed.
}

下列範例會判斷是否放開FirePrimary按鈕。The following example determines whether the FirePrimary button is released:

if (FlightStickButtons::None == (reading.Buttons & FlightStickButtons::FirePrimary))
{
    // FirePrimary is released (not pressed).
}

您有時必須要判斷按鈕何時從按下轉換為放開或從放開轉換為按下、是否按下或放開多個按鈕,或是否以特定方式排列一組按鈕 (部分為按下,部分則否)。Sometimes you might want to determine when a button transitions from pressed to released or released to pressed, whether multiple buttons are pressed or released, or if a set of buttons are arranged in a particular way—some pressed, some not. 如需如何偵測這些條件的相關資訊,請參閱偵測按鈕轉換偵測複雜按鈕排列For information on how to detect each of these conditions, see Detecting button transitions and Detecting complex button arrangements.

控制帽切換裝置的值讀取自FlightStickReading.HatSwitch屬性。The hat switch value is read from the FlightStickReading.HatSwitch property. 因為此屬性也是位元欄位,所以再一次使用位元遮罩來找出控制帽切換裝置的位置。Because this property is also a bitfield, bitwise masking is again used to isolate the position of the hat switch.

下列範例判斷控制帽切換裝置是否維持在上方位置︰The following example determines whether the hat switch is in the up position:

if (GameControllerSwitchPosition::Up == (reading.HatSwitch & GameControllerSwitchPosition::Up))
{
    // The hat switch is in the up position.
}

下列範例判斷控制帽切換裝置是否維持在中心位置︰The following example determines if the hat switch is in the center position:

if (GameControllerSwitchPosition::Center == (reading.HatSwitch & GameControllerSwitchPosition::Center))
{
    // The hat switch is in the center position.
}

另請參閱See also