飛行桿
本頁說明使用 Windows.Gaming.Input.FlightStick和相關API為Xbox One認證的飛行搖桿程式設計的基本知識。
透過閱讀此頁,您將瞭解:
- 如何收集連線的飛行搖桿及其使用者的清單
- 如何偵測飛行搖桿是否已被新增或移除
- 如何讀取一條或多條飛行搖桿中的輸入
- flight stick 作為 UI 導覽裝置的行為
飛行棒是遊戲輸入裝置,被重視用來複製在飛機或飛船駕駛艙中發現的飛行棒感覺。 是快速、精確控制飛行的理想輸入裝置。 Windows 10 或 Windows 11 和 Xbox One 應用程式透過 Windows.Gaming.Input 名稱空間支援飛行棒。
Xbox One 認證的飛行搖桿配備下列控制項:
- 一種可旋轉、俯仰和偏航的扭轉式模擬搖桿
- 模擬節流閥
- 兩個火按鈕
- 8向數位帽子開關
- 檢視和功能表按鈕
注意
View 和 Menu 按鈕用於支援 UI 導覽,而不是遊戲命令,因此不能作為搖桿按鈕輕鬆存取。
為減輕支援不同輸入裝置用於使用者介面導航的負擔,並鼓勵遊戲和裝置之間的一致性,大多數物理輸入裝置同時充當單獨的邏輯輸入裝置,稱為 UI 導航控制器。 該 UI 導航控制器提供跨輸入裝置的 UI 導航命令的公共辭彙。
作為 UI 導航控制器,飛行搖桿將所需導航命令集對映到搖桿和 View、Menu、FirePrimary、和 FireSecondary。
導覽命令 | 飛行搖桿輸入 |
---|---|
Up | 搖桿向上 |
向下 | 搖桿向下 |
Left | 搖桿向左 |
Right | 搖桿向右 |
檢視 | View 按鈕 |
功能表 | Menu 按鈕 |
Accept | FirePrimary 按鈕 |
取消 | FireSecondary 按鈕 |
飛行搖桿不會對應任何選擇的導航指令。
偵測和追蹤飛行搖桿的工作方式與遊戲板完全相同,除 FlightStick 型別而不是 Gamepad 型別。 請參閱 Gamepad and vibration,以取得更多資訊。
在你識別出你感興趣的飛行搖桿之後,你準備從它那裡收集資訊。 然而,不像其他你可能會習慣的輸入,飛行棒不會透過引發事件來傳達狀態變化。 相反,你透過輪詢 來定期檢視他們目前的狀態。
輪詢會在精確的時間點擷取試飛棒的快照。 這種輸入採集方法非常適合大多數遊戲,因為它們的邏輯通常運行在一個確定性的循環中,而不是事件驅動的。 通常情況下,從一次收集的輸入解釋遊戲命令也比從長時間收集的單個輸入解釋更加簡單。
你透過呼叫 FlightStick.GetCurrentReading,來輪詢飛行搖桿。 此函式會傳回包含 飛行搖桿狀態的 FlightStickReading。
下列範例會為目前的狀態輪詢飛行搖桿:
auto flightStick = myFlightSticks->GetAt(0);
FlightStickReading reading = flightStick->GetCurrentReading();
除飛行搖桿狀態之外,每個讀數都包括一個時間戳,精確地指示狀態被檢索的時間。 時間戳記對於與先前的讀數的時序或遊戲模擬的時序相關是有用的。
操縱桿在 X、Y 和 Z 軸 (分別為滾轉、俯仰和偏航) 上提供介於 –1.0 和 1.0 之間的模擬讀數。 對於滾輪,值 –1.0 對應於最左側的搖桿位置,值 1.0 對應於最右側的位置。 對於俯仰,值 –1.0 對應於最下方的搖桿位置,值 1.0 對應於最上方的位置。 對於偏航,值 –1.0 對應於最大逆時針扭曲位置,值 1.0 對應於最大順時針位置。
在所有軸中,當操縱桿位於中心位置時,該值約為 0.0,但精確值發生變化是正常的,即使在隨後的讀數之間也是如此。 本節稍後將討論緩解這種變化的策略。
從 FlightStickReading.Roll 屬性讀取操縱桿的滾動值,從 FlightStickReading.Pitch 屬性讀取俯仰值,從 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 列舉表示的單個位域的方向。
注意
飛行棒配備用於使用者介面導航的附加按鈕,如 View 和 Menu 按鈕。 這些按鈕不是列舉的一部分,只能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.
}