¿Puede un gamepad reemplazar el teclado? Tratando de programar con palos

imagen


Introducción



Para escribir en el teclado, debe sentarse o quedarse quieto. Los gamepads, por el contrario, son portátiles y compactos. Al controlarlos, puede caminar por la habitación o acostarse en el sofá.



Debido a la pequeña cantidad de botones en el gamepad, nadie los consideró como un medio para ingresar textos voluminosos, por ejemplo, en la programación.



Sin embargo, los sticks analógicos (y la mayoría de los gamepads tienen dos) tienen el potencial de proporcionar infinitas opciones de entrada. La cuestión se reduce a elegir los gestos correctos para obtener la máxima eficiencia y la mínima tensión en los pulgares.



Hay muchas formas de ingresar texto para gamepads. Si alguna vez ha jugado juegos de consola, es probable que haya usado uno de ellos.









Ingreso de texto en pantalla en Legend of Zelda En Legend of Zelda, el jugador debe turnarse para seleccionar letras usando el D-pad con flechas y cada vez presionando el botón de confirmación para agregar una letra al campo de ingreso de texto.



Desde entonces, se han desarrollado métodos de entrada más eficientes. Si está interesado, lea el artículo sobre Gamasutra .



Desafortunadamente, todos los métodos de entrada que he encontrado tienen dos fallas importantes que los hacen inadecuados para trabajos serios:



  • No son lo suficientemente rápidos
  • Requieren retroalimentación visual


La necesidad de velocidad es clara. La retroalimentación visual es inaceptable porque ocupa un espacio valioso en la pantalla y distrae al usuario, lo que puede interferir con el flujo y ralentizar.



Sin embargo, en ausencia de retroalimentación, todos los gestos deben memorizarse y practicarse hasta que pueda ingresarlos con suficiente precisión. Es poco probable que los videojuegos obliguen al usuario a pasar un par de semanas aprendiendo a ingresar texto, pero para encontrar una forma de ingresar texto que se pueda usar en cualquier programa, el precio es aceptable y la capacitación en sí es como dominar la entrada táctil.



En esta publicación, describiré brevemente los pasos involucrados en la creación de un sistema de entrada de texto para gamepads que se puede usar como reemplazo de la entrada de teclado volumétrico.



Decidir sobre gestos



Para empezar, creé una herramienta para visualizar el movimiento de los sticks de gamepad analógicos basados ​​en pygameel lenguaje Python. Para mayor claridad, completé la herramienta para que no solo muestre las posiciones actuales de los palos, sino también las posiciones anteriores de tonos de gris cada vez más claros, para que puedas ver los caminos por los que se mueven los palos.



La siguiente figura muestra el movimiento simultáneo de ambos joysticks analógicos hacia adentro, hacia arriba, hacia afuera, hacia abajo, hacia adentro nuevamente y de regreso al centro.





Visualizando patrones de movimiento de sticks analógicos



Lo primero que noté es que dado que el estado neutral del gamepad es encontrar los sticks en el centro, todas las opciones de entrada deben ser accesibles desde este estado neutral y todas deben terminar con el regreso de los sticks al centro.



Con estas limitaciones en mente, descubrí que la entrada más simple posible sería mover uno de los palos en cualquier dirección y de regreso al centro.





El joystick izquierdo se ha movido hacia arriba y hacia el centro.



¿Cuántas direcciones y exactamente qué direcciones puede seleccionar a ciegas? Considere el siguiente ejemplo.





El joystick izquierdo se movió hacia arriba, abajo, centro, izquierda y derecha, y el joystick derecho se movió en diagonal.Unos



pocos minutos de experimentación demostraron que era posible seleccionar direcciones con precisión a lo largo de los ejes, y la entrada en otras direcciones era mucho menos precisa (como se ve en la imagen anterior).



Los siguientes métodos de entrada más simples encontrados fueron movimientos circulares de una etapa y de dos etapas.





Joystick izquierdo movido hacia arriba, hacia la izquierda y de regreso al centro





El joystick izquierdo se movió hacia arriba, hacia la izquierda, hacia abajo y de regreso al centro



Teniendo en cuenta todos los gestos inventados hasta ahora, obtuvimos 4 + 8 + 8 = 20 opciones de entrada en cada stick.



Por supuesto, ambos sticks se pueden mover al mismo tiempo, creando gestos de entrada combinados.





Ambos sticks se mueven hacia arriba y hacia el centro al mismo tiempo.La combinación de



gestos da un total de 20 * 20 + 20 + 20 = 440 opciones de entrada, que, en mi opinión, es más que suficiente.



Gestos de codificación



Dividí el espacio de entrada de cada palo en 4 sectores y asigné un número a cada sector.



Espacios de entrada divididos en sectores


Ingrese espacios divididos en sectores



Luego establezco un área de umbral alrededor del centro para ayudar a determinar si la palanca está en la posición neutral o en uno de los sectores.





Alféizar circular alrededor del centro



Como puede ver, el radio del alféizar es bastante grande. A través de la experimentación, he determinado que este es el mejor radio que proporciona la menor cantidad de error.



Cuando alguno de los palos está descentrado, cruzando el área del umbral, comienza la secuencia de entrada. Cuando ambos palos regresan al centro dentro del área del umbral, la secuencia se considera completa y se convierte en un par de tuplas que describen el movimiento de los palos.



Movimientos de palanca para entrada ((0,), (2, 3))


Mueva las palancas para ingresar ((0,), (2, 3))



Vinculando gestos a acciones



En este caso, las acciones son solo teclas del teclado. Los botones de activación del gamepad se pueden vincular a las teclas Shift, Ctrl, Alt y Super, lo cual es conveniente porque estas teclas se usan en combinaciones (por ejemplo, Ctrl-C).



Para determinar la vinculación óptima del gesto y la tecla ingresados, usé un registrador de teclas para registrar todas las pulsaciones de teclas y analicé la frecuencia de cada tecla durante varias semanas.



Las teclas presionadas con más frecuencia deben estar ligadas a los gestos más simples (y por lo tanto, los más rápidos). Calculé la complejidad del gesto agregando las longitudes de las entradas de cada palo. Por ejemplo, la entrada que se muestra arriba ((0,), (2, 3)) tiene complejidad 1 + 2 = 3.



En este caso, al ingresar desde un stick, el uso alterno de dos sticks será más rápido que múltiples entradas desde el mismo stick, por lo que a menudo es mejor vincular las teclas que se van a escribir en diferentes sticks.



Siguiendo esta lógica, primero generé todas las opciones de entrada posibles desde un solo stick y las agrupé por dificultad. Conté el número de entradas en cada grupo de dificultad y tomé el número de claves de una lista ordenada de las claves más frecuentes.



Mi objetivo era dividir estas teclas en dos grupos, uno para la entrada del joystick izquierdo y otro para el joystick derecho. Para encontrar los grupos ideales, creé un gráfico en el que los nodos eran las teclas y los bordes ponderados eran las frecuencias de las combinaciones de teclas.



Eliminé cíclicamente el borde con el menor peso hasta que el gráfico se volvió bipartito. Si el gráfico se desconectaba, aplicaba de forma recursiva el algoritmo de partición a los componentes conectados y finalmente combinaba los grupos en conjuntos independientes.



Considere el siguiente ejemplo. El primer grupo de complejidad consta de todas las entradas con una complejidad de 1, es decir ((0,), ()), ((1,), ()), ((2,), ()), ((3,), ()), ((), (0,)), ((), (1,)), ((), (2,)), ((), (3,)).



Hay 8 entradas en este grupo, por lo que tomamos las 8 claves más frecuentes de la lista ordenada. Esto es 'e', 'o', 't', 'a', 'i', 's', 'j', 'r'. Cree un gráfico con estas claves como nodos y asigne pesos a los bordes entre estos nodos de acuerdo con la frecuencia de cada combinación de teclas.



Las teclas eyr se combinan con mayor frecuencia, por lo que deben estar unidas a diferentes palos.



Al eliminar los bordes débiles del gráfico, tarde o temprano se desvincula.

La clave j es frecuente pero aislada.


La clave j es común, pero está aislada.



Quizás se pregunte por qué la clave jes una de las 8 claves más frecuentes, pero tiene vínculos tan débiles con el resto de las claves frecuentes. La razón es que se jusa activamente cuando se trabaja con VIM plus, en mi sistema es parte de la combinación de teclas de acceso rápido para cambiar entre ventanas. Por lo tanto, se usa más a menudo de forma aislada que en el texto.



Dado que el gráfico está desconectado, sigo aplicando el algoritmo a los componentes conectados. Un subgrafo que consta solo de un nodo jya es bipartito ( j+ conjunto vacío). Estoy aplicando de forma recursiva el algoritmo a otro componente.

El componente es bipartito después de eliminar los bordes más débiles


Después de eliminar los bordes más débiles, el componente se vuelve bipartito y



, a continuación, se puede dividir fácilmente en dos grupos sin bordes entre los nodos del grupo.

Dibujo bipartito del componente


Esquema de componentes bipartitos



Al final, combino los conjuntos bipartitos.

Agrupación final de las primeras 8 claves


La agrupación obtenida para las primeras 8 teclas



Como puede ver, los enlaces más fuertes (los atajos de teclado más frecuentes) se encuentran entre los nodos en diferentes lados, que es exactamente lo que quería.



Repetí este proceso para los otros grupos de dificultad (solo entradas de un solo stick), luego generé todas las entradas combinadas posibles, las agrupé de nuevo por dificultad y asigné las teclas restantes a esas opciones de entrada. Dado que las entradas combinadas requieren el uso de ambas palancas, el problema de dividir las teclas en dos grupos no surge aquí. Usé el



paquete pyautoguiPython para generar eventos de teclado cuando se activan acciones.



Práctica



Usé el mismo entrenador táctil que ktouchya solía enseñar a escribir hace casi dos décadas. Para ello, he creado lecciones especializadas.



Practicando la escritura táctil en el mando de juegos en ktouch


Practicando la entrada analógica en un gamepad en ktouch



Observaciones



  • Aunque el proceso de Python que ejecuta este sistema de entrada generalmente no consume más del 10% de los recursos de la CPU, si tuviera que estar ejecutándose constantemente en segundo plano, lo volvería a implementar y optimizaría en un lenguaje de nivel inferior para que el procesador pueda hacer más tareas costosas.
  • Después de comprar un mando para juegos DualShock4, me di cuenta de que puedo realizar entradas diagonales con bastante precisión. La integración de la entrada diagonal reducirá el número de opciones de entrada más complejas y, por lo tanto, aumentará la velocidad.
  • , . , . , , , .
  • , . , , .
  • . .




En solo un par de días, creé un sistema de entrada eficiente para gamepads. Se pueden realizar muchas mejoras, pero esta comprobación de concepto demuestra que es posible escribir de forma eficiente en el mando. El código del proyecto está publicado en github .



All Articles