Compartilhar via


Joystick de voo

Esta página descreve os conceitos básicos de programação para joysticks de voo certificados para Xbox One, utilizando Windows.Gaming.Input.FlightStick e e as APIs relacionadas para a Plataforma Universal do Windows (UWP).

Lendo esta página, você aprenderá:

  • como reunir uma lista de palitos de voo conectados e seus usuários
  • como detectar que uma vara de voo foi adicionada ou removida
  • como ler a entrada de um ou mais joysticks de voo
  • como os joysticks de voo se comportam como dispositivos de navegação de interface do usuário

Visão geral

As varas de voo são dispositivos de entrada de jogos que são valorizados por reproduzir a sensação de varas de vôo que seriam encontradas no cockpit de um avião ou nave espacial. Eles são o dispositivo de entrada perfeito para o controle rápido e preciso do voo. Os controles de voo têm suporte nos aplicativos do Windows 10, Windows 11 e Xbox One por meio do namespace Windows.Gaming.Input.

Os flightsticks certificados pelo Xbox One são equipados com os seguintes controles:

  • Um joystick analógico giratório capaz de rolamento, inclinação e guinada
  • Um acelerador analógico
  • Dois botões de fogo
  • Um comutador de chapéu digital de 8 vias
  • Exibir botões de menu e

Observação

Os botões de Exibição e de Menu são usados para dar suporte à navegação na interface do usuário, não aos comandos de jogo, e, portanto, não podem ser facilmente acessados como botões de joystick.

Navegação da interface do usuário

Para aliviar a carga de dar suporte aos diferentes dispositivos de entrada para navegação de interface do usuário e incentivar a consistência entre jogos e dispositivos, a maioria dispositivos de entrada de físicos atuam simultaneamente como dispositivos de entrada lógicos separados chamados controladores de navegação da interface do usuário. O controlador de navegação da interface do usuário fornece um vocabulário comum para comandos de navegação da interface do usuário em dispositivos de entrada.

Como um controlador de navegação da interface do usuário, um joystick mapeia o conjunto de comandos de navegação necessários para o joystick e os botões de Exibir, Menu, FirePrimary e FireSecondary .

Comando de navegação Entrada de palito de voo
Para cima Joystick para cima
Para baixo Joystick para baixo
Esquerda Joystick à esquerda
Certo Joystick à direita
Visualizar botão Exibir
Menu Botão menu
Aceitar botão FirePrimary
Cancelar FireSecondary botão

Os controles de voo não mapeiam nenhum dos comandos de navegação opcionais do conjunto .

Detectar e rastrear palitos de voo

Detectar e rastrear varas de voo funciona exatamente da mesma maneira que funciona para gamepads, exceto com a classe FlightStick em vez da classe Gamepad. Consulte o Gamepad e a vibração para mais informações.

Lendo a vara de vôo

Depois de identificar a vara de voo em que você está interessado, você está pronto para coletar informações dele. No entanto, ao contrário de alguns outros tipos de entrada que você pode estar acostumado, os joysticks de voo não comunicam a alteração de estado gerando eventos. Em vez disso, você faz leituras regulares de seu estado atual, monitorando-as.

Sondando o bastão de vôo

A sondagem captura um instantâneo da vara de voo em um ponto preciso no tempo. Essa abordagem para a coleta de entrada é uma boa opção para a maioria dos jogos porque sua lógica normalmente é executada em um loop determinístico em vez de ser controlada por eventos. Normalmente, também é mais simples interpretar comandos de jogo da entrada coletada de uma só vez do que de muitas entradas simples coletadas ao longo do tempo.

Você sonda um bastão de voo chamando FlightStick.GetCurrentReading. Essa função retorna um FlightStickReading que contém o estado do joystick.

O exemplo a seguir sonda um bastão de voo para seu estado atual:

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

Além do estado do joystick de voo, cada leitura inclui um registro de data e hora que indica precisamente quando o estado foi obtido. O carimbo de data/hora é útil para referir-se ao tempo das leituras anteriores ou ao tempo da simulação do jogo.

Lendo o joystick e o acelerador

O joystick fornece uma leitura analógica entre -1.0 e 1.0 nos eixos X, Y e Z (rolagem, arqueamento e guinada, respectivamente). Para o roll, um valor de -1.0 corresponde à posição mais à esquerda do joystick, enquanto um valor de 1,0 corresponde à posição mais à direita. Para o pitch, um valor de -1.0 corresponde à posição mais inferior do joystick, enquanto um valor de 1,0 corresponde à posição mais alta. Para yaw, um valor de -1.0 corresponde à posição mais contra-horário, distorcida, enquanto um valor de 1.0 corresponde à posição mais no sentido horário.

Em todos os eixos, o valor é aproximadamente 0,0 quando o joystick está na posição central, mas é normal que o valor preciso varie, mesmo entre as leituras subsequentes. As estratégias para atenuar essa variação serão discutidas posteriormente nesta seção.

O valor da rolagem do joystick é lido da propriedade FlightStickReading.Roll, o valor do pitch é lido da propriedade FlightStickReading.Pitch e o valor do yaw é lido da propriedade 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;

Ao ler os valores do joystick, você observará que eles não produzem de forma confiável uma leitura neutra de 0,0 quando o joystick estiver em repouso na posição central; Em vez disso, eles produzirão valores diferentes próximos a 0,0 cada vez que o joystick for movido e retornado para a posição central. Para atenuar essas variações, você pode implementar uma pequena deadzone , que é um intervalo de valores próximo à posição central ideal que são ignorados.

Uma maneira de implementar uma zona morta é determinar o quão longe o joystick se moveu do centro e ignorar leituras mais próximas do que alguma distância que você escolher. Você pode calcular a distância aproximadamente; não é exato porque as leituras do joystick são essencialmente valores polares, não planos, apenas utilizando o Teorema de Pitágoras. Isso produz uma zona morta radial.

O exemplo a seguir demonstra um deadzone radial básico usando o teorema pitagórico:

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

Lendo os botões e o comutador de chapéu

Cada um dos dois botões de fogo do flight stick fornece uma leitura digital que indica se ele é pressionado (para baixo) ou liberado (para cima). Para obter eficiência, as leituras de botão não são representadas como valores boolianos individuais. Em vez disso, todas elas são empacotadas em um único campo de bits representado pela enumeração FlightStickButtons. Além disso, o comutador de chapéu de 8 vias fornece uma direção empacotada em um único campo de bits representado pela enumeração GameControllerSwitchPosition.

Observação

Os joysticks são equipados com botões adicionais usados para navegação da interface do usuário, como os botões de Exibição e de Menu . Esses botões não fazem parte da enumeração FlightStickButtons e só podem ser lidos acessando o flight stick como um dispositivo de navegação da interface do usuário. Para mais informações, consulte o controlador de navegação da interface do usuário .

Os valores dos botões são lidos da propriedade FlightStickReading.Buttons. Como essa propriedade é um campo de bits, o mascaramento bit a bit é usado para isolar o valor do botão no qual você está interessado. O botão é pressionado (para baixo) quando o bit correspondente é ativado; caso contrário, ele é liberado (para cima).

O exemplo a seguir determina se o botão FirePrimary é pressionado.

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

O exemplo a seguir determina se o botão FirePrimary é solto:

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

Às vezes, você pode querer determinar quando um botão passa de pressionado para solto ou de solto para pressionado, se vários botões estão pressionados ou soltos, ou se um conjunto de botões está organizado de uma maneira específica — alguns pressionados, outros não. Para obter informações sobre como detectar cada uma dessas condições, consulte Detectar transições de botão e Detectar arranjos complexos de botão.

O valor da chave do chapéu é lido da propriedade FlightStickReading.HatSwitch. Como essa propriedade também é um bitfield, a máscara de bits é novamente usada para isolar a posição do hat switch.

O exemplo a seguir determina se o comutador de chapéu está na posição de cima:

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

O exemplo a seguir determina se o comutador de chapéu está na posição central:

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

Consulte também