이 페이지에서는 Windows.Gaming.Input.FlightStick 및 UWP(유니버설 Windows 플랫폼)용 관련 API를 사용하는 Xbox One 인증 플라이트 스틱에 대한 프로그래밍의 기본 사항을 설명합니다.
이 페이지를 읽으면 다음에 대해 알아봅니다.
- 연결된 플라이트 스틱 및 해당 사용자 목록을 수집하는 방법
- 플라이트 스틱이 추가 또는 제거되었음을 감지하는 방법
- 하나 이상의 플라이트 스틱에서 입력을 읽는 방법
- 플라이트 스틱이 UI 탐색 디바이스로 동작하는 방법
개요
비행 스틱은 게임 입력 장치로, 비행기나 우주선 조종석에 있는 조작간의 느낌을 재현하는 데 높은 가치를 갖습니다. 빠르고 정확한 비행 제어를 위한 완벽한 입력 장치입니다. 플라이트 스틱은 Windows.Gaming.Input 네임스페이스를 통해 Windows 10 또는 Windows 11 및 Xbox One 앱에서 지원됩니다.
Xbox One 인증 플라이트 스틱에는 다음 컨트롤이 장착되어 있습니다.
- 회전 가능한 아날로그 조이스틱으로, 롤, 피치, 요를 조작할 수 있는
- 아날로그 스로틀
- 두 개의 화재 단추
- 8방향 디지털 모자 스위치
- 보기 및 메뉴 단추
비고
보기 및 메뉴 단추는 게임 플레이 명령이 아닌 UI 탐색을 지원하는 데 사용되므로 조이스틱 단추로 쉽게 액세스할 수 없습니다.
UI 탐색
사용자 인터페이스 탐색을 위해 다양한 입력 디바이스를 지원하는 부담을 덜고 게임과 디바이스 간의 일관성을 장려하기 위해 대부분의 물리적 입력 디바이스는 동시에 UI 탐색 컨트롤러라는 별도의 논리적 입력 디바이스 역할을. UI 탐색 컨트롤러는 입력 디바이스에서 UI 탐색 명령에 대한 일반적인 어휘를 제공합니다.
UI 탐색 컨트롤러로서 플라이트 스틱은 탐색 명령의 필수 집합 조이스틱 및 보기, 메뉴, FirePrimary및 FireSecondary 단추에 매핑합니다.
| 탐색 명령 | 플라이트 스틱 입력 |
|---|---|
| 위로 | 조이스틱 위로 이동 |
| 아래로 | 조이스틱 아래로 |
| 왼쪽 | 조이스틱 왼쪽 |
| 오른쪽 | 조이스틱 오른쪽 방향으로 |
| 보기 | 보기 버튼 |
| 메뉴 | 메뉴 단추 |
| 받아들이다 | FirePrimary 버튼 |
| 취소 | fireSecondary 단추 |
플라이트 스틱은 탐색 명령의 선택적 집합을 매핑하지 않습니다.
비행 스틱 감지 및 추적
비행 스틱을 감지하고 추적하는 것은 게임 패드와 똑같은 방식으로 작동하되, Gamepad 클래스 대신에 FlightStick 클래스를 사용합니다. 자세한 내용은 게임 패드 및 진동 참조하세요.
비행 스틱 읽기
관심 있는 조종 스틱을 식별한 후, 그로부터 입력을 수집할 준비가 된 것입니다. 그러나 다른 종류의 입력과 달리 플라이트 스틱은 이벤트를 발생시켜 상태 변경을 전달하지 않습니다. 대신에, 그들의 현재 상태를 정기적으로 확인하기 위해 폴링합니다.
비행 스틱 폴링
폴링은 정확한 시점에 비행 스틱의 스냅샷을 캡처합니다. 입력 수집에 대한 이 접근 방식은 대부분의 게임에 적합합니다. 일반적으로 논리는 이벤트 중심이 아닌 결정적 루프에서 실행되기 때문입니다. 또한 일반적으로 시간이 지남에 따라 수집된 많은 단일 입력보다 한 번에 수집된 입력에서 게임 명령을 해석하는 것이 더 간단합니다.
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은 최상위 위치에 해당합니다. 요의 경우 -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에 가까운 다른 값을 생성합니다. 이러한 변화를 완화하기 위해, 사용자는 이상적인 중심 위치 근처의 무시되는 값 범위인 작은 데드존을 구현할 수 있습니다.
데드존을 구현하는 한 가지 방법은 조이스틱이 중심에서 얼마나 멀리 이동했는지 확인하고 선택한 거리보다 가까운 판독값을 무시하는 것입니다. 파이타고란 정리를 사용하는 것만으로는 조이스틱 판독값이 기본적으로 평면 값이 아닌 극성이므로 거리를 대략적으로 계산할 수 있습니다. 방사형 데드존을 생성합니다.
다음 예제에서는 Pythagorean 정리를 사용하는 기본 방사형 데드존을 보여 줍니다.
// 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.
}
참고하십시오
- Windows.Gaming.Input.UINavigationController 클래스
- Windows.Gaming.Input.IGameController 인터페이스
- 게임 입력 방식