Diferencias clave
Las diferencias clave entre XInput y GameInput se describen en las secciones siguientes.C frente a C++
La API de XInput es una colección de funciones planas de C. GameInput, en cambio, es C++ y usa interfaces (igual que las API de gráficos y audio). En la práctica, esto no complica el código que usa la API de GameInput, no afecta al rendimiento y tiene algunas ventajas que se hacen evidentes una vez que se familiariza con el funcionamiento de GameInput. Es importante comprender que, aunque estas interfaces pueden parecer COM, no lo son. Solo se requiere una comprensión básica del recuento de referencias para usar estas interfaces. Para obtener más información, consulte la sección Interfaces del tema Aspectos básicos de GameInput.Obtención de entrada
En XInput, la mayoría de los juegos recorren en bucle los índices de usuario hasta encontrar uno con un dispositivo conectado, y luego se lee el estado de ese dispositivo. Los juegos suelen recordar el índice de usuario para no tener que repetir el bucle la próxima vez. Por ejemplo, el código siguiente es típico de un juego que pide al usuario que “presione A” en su mando:Retroalimentación de vibración
En XInput, los juegos simplemente llaman aXInputSetState para enviar comandos de vibración a un dispositivo. En GameInput, los juegos deben adquirir la instancia de IGameInputDevice del dispositivo y, a continuación, llamar a su método SetRumbleState. El uso es similar entre estos dos métodos. Este es un ejemplo de cuándo llamará a funciones en la interfaz del dispositivo, en lugar de que esta sea únicamente un identificador de dispositivo.
Foco de la aplicación
En la consola, GameInput proporciona entrada a una aplicación solo cuando esta tiene el foco. De lo contrario, el estado devuelto contiene valores neutros o de “reposo”, como si el usuario no estuviera tocando el dispositivo en absoluto. Esto elimina la necesidad de código de entrada adicional que gestione el cambio de foco (por ejemplo, llamar aXInputEnable).
En PC, la entrada llega a todos los procesos de forma predeterminada. En el futuro, este comportamiento podrá cambiarse mediante el método SetFocusPolicy.
El contenedor XInputOnGameInput
Microsoft Game Development Kit (GDK) incluye un archivo de encabezado llamadoXInputOnGameInput.h que contiene una implementación de la API de XInput sobre GameInput. Se recomienda portar directamente a GameInput, especialmente si quiere usar teclado y mouse u otros dispositivos de entrada. Sin embargo, el contenedor XInputOnGameInput se puede usar para ayudar a arrancar un esfuerzo de portabilidad inicial sin requerir ningún cambio en el código de XInput existente.
Para usar el contenedor XInputOnGameInput, simplemente reemplace este código:
Diferencias entre XInput y XInputOnGameInput
En general, el contenedor XInputOnGameInput es un reemplazo directo de la API de XInput heredada. Sin embargo, hay algunas diferencias menores:- Para simplificar, en el contenedor solo se ha codificado la compatibilidad con dispositivos de tipo mando. Si necesita compatibilidad con otros dispositivos, como volantes de carreras o joysticks arcade, use GameInput directamente o agregue compatibilidad con esos dispositivos en el código de XInputOnGameInput.
-
El contenedor devolverá entrada del mando solo cuando el juego tenga el foco. Cuando el juego no tiene el foco, cualquier estado de mando devuelto se establece en valores neutros o de “reposo”, como si el usuario no estuviera tocando el mando. Esto se hace independientemente de las llamadas a
XInputEnable(o de la ausencia de ellas). -
El valor de
XUSER_MAX_COUNTse ha aumentado de 4 a 8. En general, esto debería ser transparente para la mayoría del código de XInput heredado. Sin embargo, asegúrese de revisar cuidadosamente cualquier uso de la funciónXInputGetKeystrokeen su código para garantizar que nada esté codificado de forma rígida asumiendo que se devuelve un valor máximo de 4 en el miembroUserIndexde la estructuraXINPUT_KEYSTROKE. De lo contrario, podría producirse una saturación del búfer. - Se han agregado algunas funciones nuevas (vea a continuación) que solo deberían interesarle si tiene previsto seguir usando el contenedor de XInput en código de producción.
Uso de XInputOnGameInput en código de producción
El contenedor XInputOnGameInput está escrito para ofrecer un alto rendimiento y no usar bloqueos, heredando todas las optimizaciones de rendimiento de la API de GameInput, y por lo tanto es adecuado para usarse en código de producción. También hereda la compatibilidad más amplia con dispositivos de GameInput (como los mandos HID populares) y agrega las siguientes funciones nuevas a la API:-
XInputSetStateExes similar aXInputSetState, pero agrega compatibilidad con los motores de los gatillos. -
XInputGetStateWithTokenes similar aXInputGetState, pero permite al autor de la llamada proporcionar un token de canalización de fotogramas de D3DX para asociar una lectura de entrada específica con un fotograma de gráficos y analizarla posteriormente en PIX.[!NOTE] En la versión May Preview,
XInputGetStateWithTokense comporta actualmente de manera idéntica aXInputGetState, porque el código subyacente de GameInput no está completamente implementado. -
XInputGetDeviceIddevuelve elAPP_LOCAL_DEVICE_IDdel dispositivo en un índice de usuario determinado. Al pasar este identificador al método FindDeviceFromId de IGameInput, se devuelve el IGameInputDevice correspondiente a ese índice de usuario. Este puede usarse después para acceder a funcionalidad adicional de la API de GameInput que no está expuesta a través del contenedor de XInput.
Optimización del código del contenedor
De forma predeterminada, el contenedor XInputOnGameInput está configurado para ser un reemplazo directo compatible con la API de XInput heredada. Los juegos que no requieran un comportamiento 100 % compatible pueden ajustar el comportamiento y el rendimiento del contenedor definiendo cualquiera de las siguientes macros de preprocesador:XINPUT_ON_GAMEINPUT_EXPLICIT_INITIALIZATION
De forma predeterminada, el contenedor de XInput inicializa de forma diferida la API de GameInput subyacente automáticamente la primera vez que se llama a cualquiera de las funciones del contenedor. Esto garantiza la compatibilidad directa con el código de XInput existente, pero tiene varios inconvenientes menores:- El tiempo de ejecución de la primera llamada a una función del contenedor de XInput será más largo de lo habitual.
- Cada función del contenedor de XInput debe realizar una comprobación para ver si se ha efectuado la inicialización diferida cada vez que se la llama. Se trata de una simple comprobación de una variable global, por lo que el predictor de saltos debería mitigar el costo, pero es una sobrecarga adicional.
- Aunque nunca debería fallar, no hay forma de saber si la inicialización diferida de la API de GameInput subyacente se realizó correctamente.
- La instancia subyacente de IGameInput no se libera hasta que se limpian las variables globales del contenedor de XInput (ya sea por la descarga del módulo o por la finalización del proceso).
XINPUT_ON_GAMEINPUT_EXPLICIT_INITIALIZATION. Esto agrega dos nuevas funciones,XInputOnGameInputInitialize yXInputOnGameInputUninitialize, a las que se puede llamar para controlar con precisión cuándo se producen la inicialización y el apagado.
XINPUT_ON_GAMEINPUT_NO_XINPUTENABLE
El código necesario para implementar la funciónXInputEnable agrega una sobrecarga adicional a cada llamada de las funcionesXInputGetState,XInputGetStateWithToken,XInputSetState,XInputSetStateEx yXInputGetKeystroke. Si su código no llama aXInputEnable, o si puede eliminarse fácilmente de su código, definir la macroXINPUT_ON_GAMEINPUT_NO_XINPUTENABLE eliminará la compatibilidad conXInputEnable y la sobrecarga asociada que conlleva. De todos modos, el código subyacente de GameInput realiza automáticamente la funcionalidad deXInputEnable en los cambios de foco, por lo que la mayoría de los juegos querrán definir esta macro si pueden.
XINPUT_ON_GAMEINPUT_NO_XINPUTGETKEYSTROKE
El código necesario para implementar la funciónXInputGetKeystroke agrega algunas funciones y variables adicionales a la implementación del contenedor. No agrega sobrecarga a ninguna de las otras funciones de la API de XInput, pero si su código no llama aXInputGetKeystroke, puede definir la macroXINPUT_ON_GAMEINPUT_NO_XINPUTGETKEYSTROKE para reducir ligeramente el tamaño de código/datos del contenedor de XInput.
