共用方式為


飛行桿

此頁面說明如何使用 Windows.Gaming.Input.FlightStick 與通用 Windows 平台(UWP)的相關 API 來為 Xbox One 認證的飛行搖桿進行程式設計的基本概念。

閱讀此頁面後,您將瞭解:

  • 如何收集飛行搖桿及其使用者的連線清單
  • 如何偵測飛行搖桿是否已新增或移除
  • 如何從一或多個飛行搖桿讀取輸入
  • 飛行控制桿作為UI導航設備的行為表現如何

概觀

飛行杆是遊戲輸入設備,因能夠重現飛機或宇宙飛船駕駛艙中飛行杆的操作感而受到重視。 它們是完美的輸入設備,可快速準確地控制飛行。 飛行搖桿在 Windows 10 或 Windows 11 和 Xbox One 應用程式中均可透過 Windows.Gaming.Input 命名空間獲得支援。

Xbox One 認證的飛行棒配備下列控件:

  • 可旋轉的模擬操縱桿,能夠翻滾、俯仰和偏航
  • 類比油門
  • 兩個發射按鈕
  • 8 向帽形數位開關
  • 檢視選單 按鈕

備註

檢視功能表 按鈕是用來支援 UI 導航,而不是用於遊戲命令,因此不能輕易地作為遊戲桿按鈕來存取。

使用者介面導覽

為了減輕為使用者介面瀏覽支援不同輸入裝置的負擔,並鼓勵遊戲與裝置之間的一致性,大多數 實體 輸入設備同時作為個別的邏輯 輸入設備,稱為 UI 流覽控制器。 UI 瀏覽控制器提供跨輸入裝置的UI瀏覽命令通用詞彙。

身為UI導航控制器,飛行桿會將導航命令 所需的 對應至遊戲桿,並將 檢視MenuFirePrimary,以及 FireSecondary 按鈕。

導航命令 飛行搖桿輸入
向上 遊戲桿向上移動
向下 遊戲桿向下移動
左側 左側遊戲桿
正確 搖桿向右
查看 檢視 按鈕
菜單 選單 按鈕
接受 FirePrimary 按鈕
取消 FireSecondary 按鈕

飛行桿不會對應瀏覽命令的任何 選擇性集合

偵測和追蹤飛行搖桿

偵測和追蹤飛行搖桿的運作方式與遊戲控制器完全相同,只是使用 FlightStick 類別,而非使用 Gamepad 類別。 如需詳細資訊,請參閱 遊戲手柄和震動

閱讀飛行搖桿

識別您感興趣的飛行操作杆之後,即可準備從中收集信號。 不過,不同於您可能習慣的其他類型輸入裝置,飛行搖桿不會透過觸發事件來傳達狀態變更。 那麼,您會藉由 輪詢 來定期監測它們的目前狀態。

採樣飛行搖桿

輪詢會在精確的時間點擷取操縱桿的快照。 這種輸入收集方法最適合大部分的遊戲,因為它們的邏輯通常會在決定性循環中執行,而不是事件驅動。 從一次性收集的所有輸入解釋遊戲指令,通常比從一段時間內收集的多個單個輸入更簡單。

您可以呼叫 FlightStick.GetCurrentReading來查詢飛行杆。 此函式會傳回包含飛行桿狀態的 FlightStickReading

下列範例會查詢飛行搖桿的當前狀態:

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

除了飛行搖桿狀態之外,每個讀取都包含時間戳,精確指出狀態被擷取的時間。 時間戳適用於與先前讀取的時間或遊戲仿真的時間相關。

讀取遊戲桿和節流輸入

控制桿在 X、Y 和 Z 軸上提供-1.0 至 1.0 之間的模擬讀數(分別為滾轉、俯仰和偏航)。 若為 roll,數值為 -1.0 會對應到搖桿的最左邊位置,而數值為 1.0 則對應到最右邊位置。 對於俯仰,值為 -1.0 對應到搖桿的最下方位置,而值為 1.0 對應到搖桿的最上方位置。 若為 yaw,值為 -1.0 會對應到最逆時針、扭曲的位置,而 1.0 的值則對應至最順時針的位置。

在所有座標軸中,當遊戲桿位於中心位置時,值大約是0.0,但即使在後續的讀數中,精確值的變化也是正常的。 本節稍後將討論緩和此變化的策略。

遊戲桿的滾動值是從 FlightStickReading.Roll 属性讀取,音調的值是從 FlightStickReading.Pitch 属性讀取,而 yaw 的值則會從 FlightStickReading.Yaw 属性讀取:

// 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的不同值。 若要減輕這些變化,您可以實作小型 死區,這是忽略的理想中心位置附近的值範圍。

實作死區的方法之一是判斷遊戲桿從中央移動的距離,並忽略比您選擇的距離更近的讀數。 您可以大致計算距離,但它不精確,因為搖桿讀數基本上是極座標值,而不是平面值,只需使用畢達哥拉斯定理即可。 這會產生星形死區。

下列範例示範使用畢氏定理的基本圓形死區:

// 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.
}

讀取按鈕和帽子開關

飛行操縱桿上的兩個發射按鈕,每個按鈕都提供數位信號,指示其是否被按下(向下)或鬆開(向上)。 為了提高效率,按鈕讀數不會以個別布爾值表示,而是全部封裝成單一位域,這些位域由 FlightStickButtons 列舉表示。 此外,8 向帽形開關提供的方向被打包成單一位元欄位,並由 GameControllerSwitchPosition 列舉表示。

備註

飛行杆配備額外的按鈕,用於UI導覽,例如 檢視選單 按鈕。 這些按鈕不是 FlightStickButtons 列舉的一部分,只能透過將飛行搖桿作為UI導航裝置來讀取。 如需詳細資訊,請參閱 UI 瀏覽控制器

按鈕值會從 FlightStickReading.Buttons 屬性讀取。 由於此屬性是位元欄位,因此會使用位元遮罩來隔離您感興趣的按鈕值。 當對應的位元被設定時,按鈕被按下(向下);否則,按鈕被釋放(向上)。

下列範例會判斷 FirePrimary 按鈕是否被按下:

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

下列範例會判斷 FirePrimary 按鈕是否被放開:

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

有時候,您可能希望判斷按鈕從按下轉變到放開或從放開轉變到按下的狀態,是否有多個按鈕被按下或放開,或是判斷一組按鈕是否以某特定方式排列,即部分按下,部分未按下。 如需如何偵測每個條件的資訊,請參閱 偵測按鈕轉換偵測複雜按鈕排列

帽開關值是從 FlightStickReading.HatSwitch 屬性讀取。 由於這個屬性也是位欄位,因此會再次使用位元運算遮罩來隔離帽子開關的位置。

以下範例用來判斷帽子開關是否處於向上的位置:

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

下列範例會判斷方向帽開關是否位於中央:

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

另請參閱