Partilhar via


Manete de controlo de voo

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

Ao ler esta página, você aprenderá:

  • Como reunir uma lista de Flight Sticks conectados e seus usuários
  • Como detetar que uma bengala de voo foi adicionada ou removida
  • Como ler a entrada de um ou mais manípulos de voo
  • como os manípulos de voo se comportam como dispositivos de navegação da interface do usuário

Visão geral

Os manípulos de voo são dispositivos de entrada de jogos que são valorizados por reproduzir a sensação dos manípulos de voo que seriam encontrados no cockpit de um avião ou nave espacial. Eles são o dispositivo de entrada perfeito para um controle rápido e preciso do voo. Os bastões de voo são suportados nas aplicações Windows 10 ou Windows 11 e Xbox One através do espaço de nomes Windows.Gaming.Input .

Os manípulos de voo certificados pela Xbox One estão equipados com os seguintes controlos:

  • Um joystick analógico torcível capaz de rolamento, inclinação e guinada
  • Um acelerador analógico
  • Dois botões de fogo
  • Um interruptor de chapéu digital de 8 vias
  • Ver botões e Menu

Observação

Os botões Exibir e Menu são usados para suportar a navegação da interface do usuário, não comandos de jogo, e, portanto, não podem ser prontamente acessados como botões de joystick.

Navegação na interface do usuário

A fim de aliviar o fardo de suportar os diferentes dispositivos de entrada para a navegação na interface do usuário e incentivar a consistência entre jogos e dispositivos, a maioria dos dispositivos físicos de entrada atuam simultaneamente como dispositivos de entrada lógicos separados chamados controladores de navegação UI. 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 manípulo de vôo mapeia os de comandos de navegação necessários para o joystick e de visualização, de menu, FirePrimary e botões de FireSeconde.

Comando de navegação Entrada de manípulo de voo
Para cima Joystick para cima
Baixo Joystick para baixo
Esquerda Joystick esquerdo
Certo Joystick direito
Visualizar Ver botão
Ementa Botão Menu
Aceitar botão FirePrimary
Cancelar botão secundário de fogo

Os manípulos de voo não mapeiam nenhum dos comandos de navegação do conjunto opcional .

Detete e rastreie manípulos de voo

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

Leitura da vareta de voo

Depois de identificar a alavanca de voo em que está interessado, está pronto para recolher informações a partir dela. No entanto, ao contrário de alguns outros tipos de entrada com os quais você pode estar acostumado, as varas de voo não comunicam a mudança de estado ao gerar eventos. Em vez disso, você realiza leituras regulares de seu estado atual, consultando eles.

Votação da vara de voo

A sondagem captura uma imagem instantânea da alavanca de voo num ponto preciso no tempo. Essa abordagem de 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 orientada por eventos. Também é normalmente mais simples interpretar comandos de jogo a partir de entradas recolhidas de uma só vez do que a partir de muitas entradas únicas recolhidas ao longo do tempo.

Você verifica um joystick de voo chamando FlightStick.GetCurrentReading. Esta função devolve um FlightStickReading que contém o estado do manípulo de voo.

O exemplo a seguir sonda um manche de voo para determinar seu estado atual.

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

Além do estado do joystick de voo, cada leitura inclui um carimbo de data/hora que indica precisamente quando o estado foi recuperado. O carimbo de data/hora é útil para estabelecer uma relação com o momento das leituras anteriores ou com o momento da simulação do jogo.

Leitura das entradas do joystick e do acelerador

O joystick fornece uma leitura analógica entre -1.0 e 1.0 nos eixos X, Y e Z (rolamento, inclinação e guinada, respectivamente). Para rolo, um valor de -1,0 corresponde à posição mais à esquerda do joystick, enquanto um valor de 1,0 corresponde à posição mais à direita. Para pitch, um valor de -1,0 corresponde à posição mais inferior do joystick, enquanto um valor de 1,0 corresponde à posição mais acima. Para guinada, um valor de -1,0 corresponde à posição mais virada no sentido anti-horário, enquanto um valor de 1,0 corresponde à posição mais virada no sentido horário.

Em todos os eixos, o valor é de aproximadamente 0,0 quando o joystick está na posição central, mas é normal que o valor exato varie, mesmo entre leituras subsequentes. As estratégias para mitigar essa variação são discutidas mais adiante nesta seção.

O valor da inclinação do joystick é lido da propriedade FlightStickReading.Roll, o valor da tangagem é lido da propriedade FlightStickReading.Pitch, e o valor da guinada é 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ê notará que eles não produzem de forma confiável uma leitura neutra de 0,0 quando o joystick está 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 à posição central. Para atenuar essas variações, você pode implementar um pequeno deadzone, que é um intervalo de valores próximos à posição ideal do centro que são ignorados.

Uma maneira de implementar uma zona morta é determinar a que distância o joystick se moveu do centro e ignorar leituras que estão 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 planares – apenas usando o teorema de Pitágoras. Isso produz uma zona morta radial.

O exemplo a seguir demonstra uma zona morta radial básica usando o teorema de Pitágoras:

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

Leitura dos botões e interruptor de chapéu

Cada um dos dois botões de disparo do manípulo de vôo fornece uma leitura digital que indica se ele está pressionado (para baixo) ou liberado (para cima). Para eficiência, as leituras de botões não são representadas como valores booleanos individuais — em vez disso, todas elas são agrupadas em um único campo de bits representado pela enumeração FlightStickButtons . Além disso, o interruptor de chapéu de 8 direções fornece uma direção incorporada em apenas um campo de bits, que é representado pela enumeração GameControllerSwitchPosition.

Observação

Os manípulos de voo são equipados com botões adicionais usados para navegação na interface, como os botões View e Menu. Esses botões não fazem parte da enumeração FlightStickButtons e só podem ser lidos acessando o joystick para navegação na interface. Para obter mais informações, consulte o controlador de navegação da interface de utilizador.

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 é definido; caso contrário, é 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 é liberado:

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

Às vezes, pode-se 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á disposto de uma maneira específica — alguns pressionados, outros não. Para obter informações sobre como detetar cada uma dessas condições, consulte Detetando transições de botão e Detetando arranjos de botões complexos.

O valor do interruptor de chapéu é lido na propriedade FlightStickReading.HatSwitch. Como essa propriedade também é um campo de bits, o mascaramento bit a bit é novamente usado para isolar a posição do interruptor de chapéu.

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

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

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

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

Ver também