Principais diferenças
As principais diferenças entre o XInput e o GameInput são discutidas nas seções a seguir.C vs. C++
A API XInput é uma coleção de funções C simples. O GameInput, por outro lado, é C++ e usa interfaces (assim como as APIs de gráficos e áudio). Na prática, isso não complica o código que usa a API GameInput, não afeta o desempenho e tem algumas vantagens que se tornam evidentes à medida que você se familiariza com o funcionamento do GameInput. É importante entender que, embora essas interfaces possam parecer COM, elas não são. Apenas um entendimento básico de contagem de referências é necessário para usar essas interfaces. Para obter mais informações, confira a seção Interfaces do tópico Fundamentos do GameInput.Obtenção de entrada
No XInput, a maioria dos jogos percorre os índices de usuário em loop até encontrar um com um dispositivo conectado e, em seguida, o estado é lido desse dispositivo. Os jogos geralmente lembram o índice de usuário para não precisarem percorrer o loop na próxima vez. Por exemplo, o código a seguir é típico de um jogo que solicita ao usuário que “pressione A” no controle:Resposta de vibração
No XInput, os jogos simplesmente chamamXInputSetState para enviar comandos de vibração a um dispositivo. No GameInput, os jogos precisam obter a instância de IGameInputDevice do dispositivo e, em seguida, chamar o método SetRumbleState dela. O uso é semelhante entre esses dois métodos. Este é um exemplo de quando você chamará funções na interface do dispositivo, em vez de usá-la apenas como identificador de dispositivo.
Foco do aplicativo
No console, o GameInput fornece entrada a um aplicativo somente quando ele está em foco. Caso contrário, o estado retornado contém valores neutros ou de “repouso”, como se o usuário não estivesse tocando no dispositivo. Isso elimina a necessidade de código de entrada extra para lidar com a mudança de foco (por exemplo, chamarXInputEnable).
No PC, por padrão, a entrada vai para todos os processos. No futuro, esse comportamento poderá ser alterado usando o método SetFocusPolicy.
O wrapper XInputOnGameInput
O Microsoft Game Development Kit (GDK) é fornecido com um arquivo de cabeçalho chamadoXInputOnGameInput.h que contém uma implementação da API XInput sobre o GameInput. Recomendamos portar diretamente para o GameInput, especialmente se você quiser teclado e mouse ou outros dispositivos de entrada. No entanto, o wrapper XInputOnGameInput pode ser usado para ajudar a iniciar um esforço inicial de portabilidade sem exigir alterações no código XInput existente.
Para usar o wrapper XInputOnGameInput, basta substituir este código:
Diferenças entre o XInput e o XInputOnGameInput
Em geral, o wrapper XInputOnGameInput é um substituto direto para a API XInput legada. No entanto, há algumas pequenas diferenças:- Para simplificar, apenas o suporte a dispositivos gamepad foi codificado no wrapper. Se você precisar dar suporte a outros dispositivos, como volantes de corrida ou arcade sticks, use o GameInput diretamente ou adicione suporte a esses dispositivos no código do XInputOnGameInput.
-
O wrapper retornará a entrada do gamepad somente quando o jogo estiver em foco. Quando o jogo não estiver em foco, qualquer estado de gamepad retornado é definido com valores neutros ou de “repouso”, como se o usuário não estivesse tocando no gamepad. Isso é feito independentemente de quaisquer chamadas a
XInputEnable(ou da falta delas). -
O valor de
XUSER_MAX_COUNTfoi aumentado de 4 para 8. Em geral, isso deve ser transparente para a maior parte do código XInput legado. No entanto, revise cuidadosamente qualquer uso da funçãoXInputGetKeystrokeno seu código para ajudar a garantir que nada esteja codificado para presumir um valor máximo de 4 retornado no membroUserIndexda estruturaXINPUT_KEYSTROKE. Caso contrário, poderá ocorrer uma saturação de buffer. - Algumas novas funções foram adicionadas (veja a seguir), que devem interessar apenas se você pretende continuar usando o wrapper XInput em código de produção.
Uso do XInputOnGameInput em código de produção
O wrapper XInputOnGameInput foi escrito para ser de alto desempenho e livre de bloqueio, herdando todas as otimizações de desempenho da API GameInput e, portanto, é adequado para uso em código de produção. Ele também herda o suporte mais amplo a dispositivos do GameInput (como gamepads HID populares) e adiciona as seguintes novas funções à API:-
XInputSetStateExé semelhante aXInputSetState, mas adiciona suporte aos motores dos gatilhos. -
XInputGetStateWithTokené semelhante aXInputGetState, mas permite que o chamador forneça um token de pipeline de quadro D3DX para associar uma leitura de entrada específica a um quadro gráfico para análise posterior no PIX.[!NOTE] Na versão May Preview,
XInputGetStateWithTokenatualmente se comporta de forma idêntica aXInputGetState, porque o código subjacente do GameInput não está totalmente implementado. -
XInputGetDeviceIdretorna oAPP_LOCAL_DEVICE_IDdo dispositivo em um determinado índice de usuário. Passar essa ID para o método FindDeviceFromId em IGameInput retorna o IGameInputDevice correspondente a esse índice de usuário. Isso pode então ser usado para acessar funcionalidades adicionais da API GameInput que não são expostas pelo wrapper XInput.
Otimização do código do wrapper
Por padrão, o wrapper XInputOnGameInput é configurado para ser um substituto direto compatível com a API XInput legada. Os jogos que não exigem comportamento 100% compatível podem ajustar o comportamento e o desempenho do wrapper definindo qualquer uma das seguintes macros de pré-processador:XINPUT_ON_GAMEINPUT_EXPLICIT_INITIALIZATION
Por padrão, o wrapper XInput inicializa de forma lenta a API GameInput subjacente automaticamente na primeira vez em que qualquer uma das funções do wrapper é chamada. Isso garante a compatibilidade direta com o código XInput existente, mas tem várias pequenas desvantagens:- O tempo de execução da primeira chamada de função do wrapper XInput será maior do que o normal.
- Toda função do wrapper XInput precisa verificar se a inicialização lenta foi realizada sempre que é chamada. Esse é um teste simples de uma variável global, portanto, o preditor de desvios deve amenizar o custo, mas é uma sobrecarga extra.
- Embora nunca deva falhar, não há como saber se a inicialização lenta da API GameInput subjacente foi bem-sucedida.
- A instância subjacente de IGameInput não é liberada até que as variáveis globais do wrapper XInput sejam limpas (seja devido ao descarregamento do módulo ou ao encerramento do processo).
XINPUT_ON_GAMEINPUT_EXPLICIT_INITIALIZATION. Isso adiciona duas novas funções,XInputOnGameInputInitialize eXInputOnGameInputUninitialize, que podem ser chamadas para controlar com precisão quando a inicialização e o desligamento ocorrem.
XINPUT_ON_GAMEINPUT_NO_XINPUTENABLE
O código necessário para implementar a funçãoXInputEnable adiciona sobrecarga extra a cada chamada das funçõesXInputGetState,XInputGetStateWithToken,XInputSetState,XInputSetStateEx eXInputGetKeystroke. Se o seu código não chamaXInputEnable, ou se essa chamada puder ser facilmente eliminada do seu código, definir a macroXINPUT_ON_GAMEINPUT_NO_XINPUTENABLE removerá o suporte aXInputEnable e a sobrecarga associada. De qualquer forma, o código subjacente do GameInput executa automaticamente a funcionalidade deXInputEnable nas mudanças de foco, portanto, a maioria dos jogos vai querer definir essa macro, se puder.
XINPUT_ON_GAMEINPUT_NO_XINPUTGETKEYSTROKE
O código necessário para implementar a funçãoXInputGetKeystroke adiciona algumas funções e variáveis extras à implementação do wrapper. Ele não adiciona sobrecarga a nenhuma das outras funções da API XInput, mas, se o seu código não chamaXInputGetKeystroke, você pode definir a macroXINPUT_ON_GAMEINPUT_NO_XINPUTGETKEYSTROKE para diminuir ligeiramente o tamanho do código/dados do wrapper XInput.
