Controlador de navegación de la interfaz de usuario

En esta página se describen los conceptos básicos de programación para dispositivos de navegación de la interfaz de usuario mediante Windows.Gaming.Input.UINavigationController y las API relacionadas para el Plataforma universal de Windows (UWP).

En esta página encontrarás información sobre:

  • Cómo obtener una lista de los dispositivos de navegación de la interfaz de usuario conectados y sus usuarios
  • Cómo detectar que se ha agregado o quitado un dispositivo de navegación
  • Cómo leer la entrada desde uno o varios dispositivos de navegación de la interfaz de usuario
  • Cómo se comportan los controladores para juegos y los sticks arcade como dispositivos de navegación

Información general sobre controladores de navegación de la interfaz de usuario

Casi todos los juegos tienen al menos alguna interfaz de usuario que es independiente del juego, aunque se trate simplemente de menús previos al juego o cuadros de diálogo en el juego. Los jugadores deben poder navegar por la interfaz de usuario con cualquier dispositivo de entrada que hayan elegido, pero esto resulta abrumador para los desarrolladores, ya que deben agregar compatibilidad específica para cada tipo de dispositivo de entrada y, además, puede producir incoherencias entre los juegos y los dispositivos de entrada que confunden a los jugadores. Por estas razones, se creó la API UINavigationController.

Los controladores de navegación de la interfaz de usuario son dispositivos de entrada lógicos que existen para proporcionar un vocabulario general de comandos de navegación de la interfaz de usuario que puede ser compatible con diversos dispositivos de entrada físicos. Un controlador de navegación de la interfaz de usuario es, simplemente, otra forma de denominar un dispositivo de entrada físico. Usamos el término dispositivo de navegación para hacer referencia a cualquier dispositivo de entrada físico que se considera un controlador de navegación. Al programar con un dispositivo de navegación en lugar de dispositivos de entrada específicos, los desarrolladores evitan la carga de tener que agregar compatibilidad para diferentes dispositivos de entrada y logran uniformidad de manera predeterminada.

Dado que el número y la diversidad de controles compatibles con cada tipo de dispositivo de entrada pueden diferir mucho y que determinados dispositivos de entrada podrían querer admitir un conjunto más amplio de comandos de navegación, la interfaz de controladores de navegación divide el vocabulario de comandos en un conjunto necesario, que contiene los comandos más habituales y esenciales, y un conjunto opcional, que contiene comandos convenientes, pero no esenciales. Todos los dispositivos de navegación admiten todos los comandos del conjunto necesario y pueden admitir la totalidad, algunos o ninguno de los comandos del conjunto opcional.

Conjunto necesario

Los dispositivos de navegación deben admitir todos los comandos de navegación del conjunto necesario. Se trata de los comandos direccionales (arriba, abajo, izquierda y derecha) y los comandos ver, menú, aceptar y cancelar.

Los comandos direccionales están destinados a la navegación con foco XY principal entre elementos únicos de la interfaz de usuario. Los comandos "ver" y "menú" están pensados para mostrar información de juego (suelen ser momentáneos, a veces de forma modal) y para cambiar entre los contextos de juego y menú, respectivamente. Los comandos "aceptar" y "cancelar" están destinados a las respuestas afirmativa (sí) y negativa (no), respectivamente.

En la siguiente tabla se muestra un resumen de estos comandos y sus usos previstos, con ejemplos. | Comando | Uso previsto | -------:| --------------- | Arriba | Navegación con foco XY | Abajo | Navegación con foco XY hacia abajo | Izquierda | Navegación con foco XY a la izquierda | Derecha | Navegación con foco XY a la derecha | Vista | Mostrar información de juego (cuadro de mandos, estadísticas de juego, objetivos, mapa de mundo o área) | Menú | Menú principal/Pausa (configuración, estado, equipo, inventario, pausa) | Aceptar | Respuesta afirmativa (aceptar, avanzar, confirmar, iniciar, sí) | Cancelar | Respuesta negativa (rechazar, invertir, rechazar, detener, no)

Conjunto opcional

Es posible que los dispositivos de navegación también admitan la totalidad, algunos o ninguno de los comandos de navegación del conjunto opcional. Se trata de comandos de paginación (arriba, abajo, izquierda y derecha), desplazamiento (arriba, abajo, izquierda y derecha) y contextuales (contexto de 1 a 4).

Los comandos contextuales están explícitamente pensados para los comandos específicos de la aplicación y los accesos directos de navegación. Los comandos de paginación y desplazamiento están destinados a navegar rápidamente entre páginas o grupos de elementos de la interfaz de usuario y para la navegación específica dentro de los elementos de la interfaz de usuario, respectivamente.

En la siguiente tabla se muestra un resumen de estos comandos y sus usos previstos. | Comando | Uso previsto | -----------:| ------------ | PageUp | Saltar hacia arriba (hasta la página o grupo vertical superior/anterior) | PageDown | Saltar hacia abajo (hacia abajo/siguiente página vertical o grupo) | PageLeft | Saltar a la izquierda (hacia la izquierda/hacia la izquierda/página horizontal anterior o grupo) | PageRight | Saltar hacia la derecha (hacia la derecha/siguiente página horizontal o grupo) | ScrollUp | Desplazarse hacia arriba (dentro del elemento de interfaz de usuario centrado o del grupo desplazable) | ScrollDown | Desplazarse hacia abajo (dentro del elemento de interfaz de usuario centrado o del grupo desplazable) | ScrollLeft | Desplazarse a la izquierda (dentro del elemento de interfaz de usuario centrado o del grupo desplazable) | ScrollRight | Desplazarse a la derecha (dentro del elemento de interfaz de usuario centrado o grupo desplazable) | Context1 | Acción de contexto principal | Context2 | Acción de contexto secundario | Context3 | Tercera acción de contexto | Context4 | Cuarta acción de contexto

Nota Aunque un juego es libre de responder a cualquier comando con una función real que sea diferente de su uso previsto, se debe evitar un comportamiento sorprendente. En concreto, no cambies la función real de un comando si necesitas su uso previsto. Trata de asignar funciones nuevas para el comando que sea más acorde a esas funciones y asigna funciones equivalentes a comandos equivalentes como PageUp o PageDown. Por último, considera qué comandos son compatibles con cada tipo de dispositivo de entrada y a qué controles están asignados, para así asegurarte de que los comandos críticos sean accesibles desde todos los dispositivos.

Navegación mediante controlador para juegos, stick arcade y volante

Todos los dispositivos de entrada admitidos por el espacio de nombres Windows.Gaming.Input son dispositivos de navegación de la interfaz de usuario.

En la siguiente tabla se resume cómo el conjunto necesario de comandos de navegación se asigna a diversos dispositivos de entrada.

Comando de navegación Entrada del controlador para juegos Entrada del stick arcade Entrada del volante
Subir Stick analógico izquierdo hacia arriba/cruceta hacia arriba Stick hacia arriba Cruceta hacia arriba
Bajar Stick analógico izquierdo hacia abajo/cruceta hacia abajo Stick hacia abajo Cruceta hacia abajo
Left Stick analógico izquierdo hacia la izquierda/cruceta hacia la izquierda Stick hacia la izquierda Cruceta hacia la izquierda
Right Stick analógico izquierdo hacia la derecha/cruceta hacia la derecha Stick hacia la derecha Cruceta hacia la derecha
Ver Botón de vista Botón de vista Botón de vista
Menú Botón de menú Botón de menú Botón de menú
Aceptar Botón A Botón de acción 1 Botón A
Cancelar Botón B Botón de acción 2 Botón B

En la siguiente tabla se resume cómo el conjunto opcional de comandos de navegación se asigna a diversos dispositivos de entrada.

Comando de navegación Entrada del controlador para juegos Entrada del stick arcade Entrada del volante
RePág Gatillo izquierdo no se admite varía
AvPág Gatillo derecho no se admite varía
PageLeft Botón superior izquierdo no se admite varía
PageRight Botón superior derecho no se admite varía
ScrollUp Stick analógico derecho hacia arriba no se admite varía
ScrollDown Stick analógico derecho hacia abajo no compatible varía
ScrollLeft Stick analógico derecho hacia la izquierda no compatible varía
ScrollRight Stick analógico derecho hacia la derecha no compatible varía
Context1 Botón X no compatible Botón X (generalmente)
Context2 Botón Y no compatible Botón Y (generalmente)
Context3 Presión del stick analógico izquierdo no compatible varía
Context4 Presión del stick analógico derecho no compatible varía

Detectar y realizar un seguimiento de los controladores de navegación de la interfaz de usuario

Aunque los controladores de navegación de la interfaz de usuario son dispositivos de entrada lógicos, son una representación de un dispositivo físico y el sistema los administra de la misma forma. No tienes que crearlos o inicializarlos, ya que el sistema proporciona una lista de eventos y controladores de navegación de la interfaz de usuario conectados para notificarte cuando se agrega o se quita un controlador de navegación de la interfaz de usuario.

Lista de controladores de navegación de la interfaz de usuario

La clase UINavigationController proporciona una propiedad estática, UINavigationControllers, que es una lista de solo lectura de los dispositivos de navegación de la interfaz de usuario que están actualmente conectados. Dado que, probablemente, solo te interesen algunos de los dispositivos conectados, es conveniente mantener tu propia colección en lugar de acceder a ellos a través de la propiedad UINavigationControllers.

En el siguiente ejemplo, se copian todos los controladores de navegación de la interfaz de usuario conectados a una nueva colección.

auto myNavigationControllers = ref new Vector<UINavigationController^>();

for (auto device : UINavigationController::UINavigationControllers)
{
    // This code assumes that you're interested in all navigation controllers.
    myNavigationControllers->Append(device);
}

Agregar y quitar controladores de navegación de la interfaz de usuario

Cuando se agrega o se quita un controlador de navegación de la interfaz de usuario, se generan los eventos UINavigationControllerAdded y UINavigationControllerRemoved. Puedes registrar un controlador de eventos para estos eventos con el fin de hacer un seguimiento de los dispositivos de navegación que están actualmente conectados.

En el siguiente ejemplo, se inicia el seguimiento de un dispositivo de navegación de la interfaz de usuario que se ha agregado.

UINavigationController::UINavigationControllerAdded += ref new EventHandler<UINavigationController^>(Platform::Object^, UINavigationController^ args)
{
    // This code assumes that you're interested in all new navigation controllers.
    myNavigationControllers->Append(args);
}

En el siguiente ejemplo, se detiene el seguimiento de un stick arcade que se ha quitado.

UINavigationController::UINavigationControllerRemoved += ref new EventHandler<UINavigationController^>(Platform::Object^, UINavigationController^ args)
{
    unsigned int indexRemoved;

    if(myNavigationControllers->IndexOf(args, &indexRemoved))
	{
        myNavigationControllers->RemoveAt(indexRemoved);
    }
}

Usuarios y auriculares

Cada dispositivo de navegación puede asociarse con una cuenta de usuario para vincular su identidad a su entrada y puede tener conectados unos auriculares para facilitar las características de navegación o chat de voz. Para obtener más información sobre cómo trabajar con usuarios y auriculares, consulta Tracking users and their devices (Seguimiento de usuarios y sus dispositivos) y Headset (Auriculares).

Leer el controlador de navegación de la interfaz de usuario

Después de identificar el dispositivo de navegación de la interfaz de usuario que te interesa, puedes recopilar su entrada. Sin embargo, a diferencia de algunos otros tipos de entrada con los que puedas estar familiarizado, los dispositivos de navegación no comunican el cambio de estado mediante la generación de eventos. En cambio, tienes que realizar lecturas regulares de su estado actual mediante sondeos.

Sondear el controlador de navegación de la interfaz de usuario

El sondeo captura una instantánea del dispositivo de navegación en un momento preciso en el tiempo. Este enfoque de recopilación de entrada es una buena opción para la mayoría de los juegos porque su lógica, normalmente, se ejecuta en un bucle determinista en lugar de controlarse mediante eventos. También suele ser más sencillo interpretar los comandos de juego de la entrada recopilada de una vez que de muchas entradas individuales recopiladas a lo largo del tiempo.

El sondeo de un dispositivo de navegación se realiza mediante una llamada a UINavigationController.GetCurrentReading. Esta función devuelve una estructura UINavigationReading que contiene el estado del dispositivo de navegación.

auto navigationController = myNavigationControllers[0];

UINavigationReading reading = navigationController->GetCurrentReading();

Lectura de los botones

Cada uno de los botones de navegación de la interfaz de usuario proporciona una lectura booleana que corresponde a si se lo presiona (abajo) o libera (arriba). Por motivos de eficacia, las lecturas de botones no se representan como valores booleanos individuales, sino que todos se incorporan en uno de los dos campos de bits representados por las enumeraciones RequiredUINavigationButtons y OptionalUINavigationButtons.

Los botones pertenecientes al conjunto necesario se leen desde la propiedad RequiredButtons de la estructura UINavigationReading y los botones pertenecientes al conjunto opcional se leen desde la propiedad OptionalButtons. Dado que estas propiedades son campos de bits, se usa el enmascaramiento bit a bit para aislar el valor del botón que te interesa. El botón está presionado (abajo) cuando se establece el bit correspondiente; de lo contrario, no lo está (arriba).

En el ejemplo siguiente, se determina si el botón Aceptar del conjunto necesario está presionado.

if (RequiredUINavigationButtons::Accept == (reading.RequiredButtons & RequiredUINavigationButtons::Accept))
{
    // Accept is pressed
}

En el ejemplo siguiente, se determina si el botón Aceptar del conjunto necesario está liberado.

if (RequiredUINavigationButtons::None == (reading.RequiredButtons & RequiredUINavigationButtons::Accept))
{
    // Accept is released (not pressed)
}

Asegúrate de usar la propiedad OptionalButtons y la enumeración OptionalUINavigationButtons al leer botones del conjunto opcional.

En el ejemplo siguiente, se determina si el botón Contexto 1 del conjunto opcional está presionado.

if (OptionalUINavigationButtons::Context1 == (reading.OptionalButtons & OptionalUINavigationButtons::Context1))
{
    // Context 1 is pressed
}

A veces, tal vez quieras determinar si se libera un botón que está presionado o si se presiona un botón que no lo estaba, si se presionan o liberan varios botones o si un conjunto de botones tiene una disposición determinada (algunos presionados y otros no). Para obtener información sobre cómo detectar estas condiciones, consulta Detección de transiciones de botón y Detección disposiciones de botones complejas.

Ejecutar la muestra de controlador de navegación de la interfaz de usuario

La muestra InputInterfacingUWP (GitHub) evidencia cómo los distintos dispositivos de entrada se comportan como controladores de navegación de la interfaz de usuario.

Vea también

Windows.Gaming.Input.GamepadWindows.Gaming.Input.ArcadeStickWindows.Gaming.Input.RacingWheelWindows.Gaming.Input.IGameController