GamePad en Flutter y Flame - Dualsense - Xbox

El GamePad es el mecanismo por excelencia para jugar a videojuegos y uno de los primeros elementos que se nos vienen a la cabeza cuando escuchamos la palabra videojuego o consola de videojuegos; utilizar este tipo de controles para nuestros juegos no es imposible; sin embargo, en Flame, no tenemos muchas opciones; en la documentación oficial, veremos que al momento en que se escribieron estas palabras, existe un apartado muy corto que menciona el uso del gamepad en Flame:

https://docs.flame-engine.org/latest/flame/inputs/other_inputs.html

El problema con el paquete que hacen mención:

https://github.com/flame-engine/flame_gamepad

Es que al momento en el que se escribieron estas palabras, lleva más de 3 años sin actualizar y en el desarrollo de software, que incluye el desarrollo de videojuegos, es un tiempo considerablemente largo, por lo tanto, personalmente no recomendaría su uso ya que pueden existir problemas de versiones de paquete con el proyecto actual lo que traería problemas en la implementación.

En Flutter (No directamente Flame, si no el framework conocido como Flutter) existen unos pocos plugins que podemos usar; por ejemplo este:

https://pub.dev/packages/gamepads

Al momento en el cual se escribieron estas palabras, el paquete se encuentra en desarrollo, por lo tanto, su documentación es muy escasa y su implementación no es del todo amigable como veremos en el apartado de la implementación; sin embargo, es un paquete que tiene potencial y está en constante desarrollo, por lo tanto es el que vamos a emplear; es importante mencionar que este paquete no está diseñado para Flame, al igual que el paquete de Sharedpreferences, pero, podemos usarlo sin problemas en un proyecto con Flutter y Flame; actualmente este paquete no está disponible para web o móvil.

Primeros pasos con el plugin gamepads

Comencemos agregando la dependencia para el paquete anterior:

pubspec.yaml

dependencies:
  flutter:
    sdk: flutter
  ***
  gamepads:

El cual cuenta con 2 clases principales:

  1. GamepadController: Representa un solo gamepad actualmente conectado.
  2. GamepadEvent: Es un evento que se construye al momento de que ocurre una entrada desde un gamepad, en otras palabras, al momento de presionar una tecla, se construye un evento de este tipo.

La clase GamepadEvent contiene las siguientes propiedades:

class GamepadEvent {
  // El id asignado al gamepad que disparó el evento.
  final String gamepadId;

  // La marca de tiempo en la que se disparó el evento, en milisegundos.
  final int timestamp;

  // El [KeyType] de la tecla que se pulso.
  final KeyType type;

  // Un identificador del boton/analog pulsado.
  final String key;

  // El valor actual del boton/analog pulsado.
  final double value;
}

Las más importantes serían la de key, que indica la tecla presionada y la de value, con la cual, dependiendo del tipo de botón presionado, podemos conocer el ángulo o si fue presionado o liberado el botón.

El tipo de entrada pueden ser de dos tipos que es representado mediante un tipo enumerado llamado KeyType:

  1. analog: Las entradas analógicas tienen un rango de valores posibles dependiendo de qué tan lejos/fuerte se presionen (representan palancas analógicas, disparadores traseros, algunos tipos de d-pads (crucetas), etc.)
  2. button: Los botones tienen solo dos estados, presionado (1.0) o no (0.0).

Definir un listeners para detectar teclas presionadas

Para este plugin, tenemos dos usos principales, conocer la cantidad de controles conectados; para ello:

gamepads = await Gamepads.list()

O crear un listeners que permite escuchar las teclas presionadas sobre todos los gamepads conectados:

Gamepads.events.listen((GamepadEvent event) { });

Como puedes apreciar, aqui tenemos el evento GamepadEvent que tiene la estructura mencionada antes; como puedes apreciar, el uso del paquete es extremadamente simple, ya que, no requiere de establecer un control conectado o algo similar, automáticamente tenemos un listeners de todos los controles conectados al dispositivo; desde el componente de player, colocamos el listener para el gamepad:

import 'package:gamepads/gamepads.dart';
***
@override
Future<void>? onLoad() async {
  // final gamepads = await Gamepads.list();
  // print('Gamepads' + gamepads.toString());
  Gamepads.events.listen((GamepadEvent event) {
    print("gamepadId" + event.gamepadId);
    print("timestamp" + event.timestamp.toString());
    print("type   " + event.type.toString());
    print("key   " + event.key.toString());
    print("value   " + event.value.toString());
  });
}

Como recomendación conecta algún dispositivo a tu PC/Mac, mediante Bluetooth o su cable USB, inicia la aplicación y empieza a presionar algunos botones en el gamepad, incluyendo sus joystick y crucetas y analiza la respuesta, verás que algunos son propiamente "button" y otros son "analog" en base a la clasificación por tipos mencionada anteriormente, en el caso de los botones, verás que el listener anterior se ejecuta cuando se presiona y libera el botón.

En base a pruebas realizadas desde un dispositivo Windows 11 con un control de Xbox S|X, tenemos la siguiente implementación para detectar la tecla "A":

import 'package:gamepads/gamepads.dart';
***
@override
Future<void>? onLoad() async {
  // final gamepads = await Gamepads.list();
  // print('Gamepads' + gamepads.toString());
  Gamepads.events.listen((GamepadEvent event) {
    // print("gamepadId" + event.gamepadId);
    // print("timestamp" + event.timestamp.toString());
    // print("type   " + event.type.toString());
    // print("key   " + event.key.toString());
    // print("value   " + event.value.toString());

    if (event.key == 'button-0' && event.value == 1.0) {
      print('rotar');
    }
  });
}

Y para la cruceta, detectar el desplazamiento:

import 'package:gamepads/gamepads.dart';
***
@override
Future<void>? onLoad() async {
  Gamepads.events.listen((GamepadEvent event) {

    if (event.key == 'button-0' && event.value == 1.0) {
      print('jump');
    } else if (event.key == 'pov' && event.value == 0.0) {
      // up
      print('up');
    } else if (event.key == 'pov' && event.value == 4500.0) {
      // up - right
      print('up - right');
    } else if (event.key == 'pov' && event.value == 9000.0) {
      // right
      print('right');
    } else if (event.key == 'pov' && event.value == 13500.0) {
      // buttom right
      print('buttom right');
    } else if (event.key == 'pov' && event.value == 18000.0) {
      // buttom
      print('buttom');
    } else if (event.key == 'pov' && event.value == 22500.0) {
      // buttom left
      print('buttom left');
    } else if (event.key == 'pov' && event.value == 27000.0) {
      // left
      print('left');
    } else if (event.key == 'pov' && event.value == 31500.0) {
      // top left
      print('top left');
    }
  });
}

El caso de la cruceta es interesante ya que, según el plugin utilizado, corresponde a un mismo botón, por lo tanto, al presionar "flecha arriba" tenemos un valor de 0.0, al presionar "flecha abajo" tenemos un valor de 18000, como puedes ver, son valores que corresponden a un espacio de 360 grados; por lo tanto, podemos personalizar la experiencia como queramos; finalmente, la implementación usando la cruceta queda como:

import 'package:gamepads/gamepads.dart';
***
@override
FutureOr<void> onLoad() async {
  // var gamepads = await Gamepads.list();
  // print('*******');
  // print(gamepads.toString());

  Gamepads.events.listen((GamepadEvent event) {
    
    if (event.key == 'button-0' && event.value == 1.0) {
      // print('Rotate');
      _rotate();
    } else if (event.key == 'pov' && event.value == 0) {
      // up
      // print('up');
      movementType = MovementType.up;
    } else if (event.key == 'pov' && event.value == 4500) {
      // up right
      // print('up right');
    } else if (event.key == 'pov' && event.value == 9000) {
      // right
      // print('right');
      movementType = MovementType.right;
    } else if (event.key == 'pov' && event.value == 13500) {
      // buttom right
      // print('buttom right');
    } else if (event.key == 'pov' && event.value == 18000) {
      //bottom
      // print('bottom');
      movementType = MovementType.down;
    } else if (event.key == 'pov' && event.value == 22500) {
      // buttom left
      // print('buttom left');
    } else if (event.key == 'pov' && event.value == 27000) {
      // left
      // print('left');
      movementType = MovementType.left;
    } else if (event.key == 'pov' && event.value == 31500) {
      // top left
      // print('top left');
    } else {
      movementType = MovementType.idle;
      //
    }
  });
  ***
}

Claro está, es posible que estos valores cambien si usas otro tipo de control o en versiones futuras del plugin por lo tanto, se recomienda al lector que adecue el script anterior a sus necesidades.

Con esta implementación, tenemos otras entradas para los juegos que hemos implementado en este libro y que por supuesto puedes adaptar a otros como el juego del dinosaurio.

Transcripción del vídeo

En esta sección vamos a resolver algunos pequeños detalles finales sobre nuestro juego también detalles finales que podemos ampliar para otras implementaciones como sería el shared preference que seguramente lo conoces o el Router, Espero que lo conozcas de flutter es un mecanismo que tenemos por excelencia para guardar datos de usuario en este caso a todo usuario van a ser datos del juego que serían por ejemplo el nivel y el tipo de juego Por ejemplo si vengo acá y selecciono el nivel monoruro que exista creo que el 2 aquí coloco nivel 2 vengo acá mi visual Studio code y reinicio vas a ver que todavía prevalece el nivel 2 y lo mismo con el tipo de juego vengo acá selecciono el tipo de juego Bueno tengo toda esta novela de nombre y reinicio todavía se mantiene recuerda aquí aquí cuando seleccionamos el tipo de juego automáticamente pasa a nivel 1 cosa que puedes cambiar Pero al menos así la implementación que realizamos y así la dejé esta característica como te cuento puedes implementarla en el resto de los videojuegos que creamos Pero bueno aparte de eso también creamos un par de mecanismos para poder interactuar con el juego el problema que teníamos actualmente es que necesitamos interactuar con el teclado cosa que no es completamente correcta ya que si quieres ejecutar el juego móvil entonces tendrías que obligar al usuario es decir al usuario final hay que Conectar a un teclado a su dispositivo Android o iOS una tableta sea lo que sea que emplee cosa que lógicamente no es correcta qué fue lo que hicimos para resolver Esto bueno básicamente aquí crear un joystick virtual tal cual puedes ver esto ya no los provee de flame por lo tanto la integración fue relativamente sencilla y por aquí también un botón para rotar al Player por supuesto pues implementar más botones en caso de que sea necesario inclusive más joystick en caso de que sea necesario pero bueno en este caso implementamos fue este que sería el único necesario para este juego Entonces qué más hicimos tal cual puedes ver en otro vídeo que se está ejecutando anexo este también implementamos un gamepad para poder desplazar a nuestro Player claro al menos de momento al momento en el cual grabe este video el paquete que empleamos no es directamente que nos indica flame que puedes consultarla en la documentación oficial en la sección de otras entradas es que ese paquete tiene mucho tiempo sin actualizarse por lo tanto empleamos otra solución una directamente para flutter que adaptamos para nuestra aplicación en Play Pero ese paquete tiene algunas carencias Y es que, solamente se emplea en móvil es decir, Android e iOS así que bueno Esto es lo que nosotros vamos a hacer en esta sección Y recuerda que esta misma solución la puedes implementar en el resto de los videojuegos que ya creamos y que vayamos a seguir creando en este curso Ok antes de comenzar a trabajar con el gamepad quería hacer una pequeña introducción de qué es lo que tenemos como estamos al momento en el cual grabé Este vídeo Cuál es el ecosistema Y qué es lo que tenemos a nuestra disposición Así que para eso voy a hacer esta pequeña presentación yo creo que cuando escucha la palabra en gamepad No hay ninguna duda al respecto sobre Qué es este componente de igual manera se lo hay Recuerda que puedes buscar aquí en internet y bueno por aquí vas a ver un gamepad un gamepad es básicamente lo que llamamos coloquialmente como un control de videojuegos es decir el siguiente elemento que puedes ver en pantalla lo más famoso son los del Dual bueno el sol no el sensor o no sé cómo que se llama el de sonido este que tenemos ahorita Acá del PlayStation 5 Y por supuesto el del Xbox y también el de Nintendo switch el del Xbox es este que te lo voy a mostrar porque es el que yo voy a emplear en esta presentación Xbox s control Bueno ese o x cualquiera de los dos son estos que vemos por acá justamente Este es el que voy a emplear Pero nuevamente puedes emplear cualquier otro en caso de que no lo tengas aquí es donde viene lo interesante el asunto para la prueba que al menos yo voy a hacer particularmente solamente voy a emplear un control ya que solamente dispongo de este tipo de controles actualmente no tengo de PlayStation y no tengo ninguno de otro estilo Aunque en principio con que lo reconozca el PC es condición suficiente para que lo puedas emplear Entonces eso es básicamente lo que vamos a querer adaptar a nuestra aplicación creo que la razón es obvia Mientras más elementos tengamos para interactuar con el juego ya hemos presentado para esta serie tercero hemos presentado el del teclado que fue siempre que empleamos mayormente también presentamos el de joystick virtual y esto También incluye lo que eran otros elementos por ejemplo el botón que empleamos para rotar a nuestro Player y ahora vamos a presentar otro que sea gamepad para ver cómo funciona y cómo lo podemos utilizar por aquí en play por lo demás ojo más que decir Entonces vamos a ver qué es lo que tenemos actualmente para poder enviarlo.

Plugin para el Gamepad en Flame

Así que para este voy a ir aquí a la documentación oficial y bueno Y aquí ya tengo el enlace de igual manera ahorita ves como puedes Ingresar a este enlace para que tú también veas en lo que existe actualmente ya que puede que lo cambien Aquí yo estoy a la última versión tal cual puedes ver la que hice las y por aquí en input la que dice otros impotencias y otras entradas aquí tenemos el de joystick que también le puedes echar un ojo y al final de todo tenemos el de gamepad Qué bueno lo definen básicamente una línea y media en la cual nos indica que esto trabaja con un plugin separado y puedes tener más información dándole Aquí vamos a ver qué es lo que tenemos actualmente a la fecha al menos al momento en el cual grabe este video Este plugin lo puedo considerar que está prácticamente abandonado ya que un paquete para mí que tiene más de dos años por lo mucho y dependiendo del paquete pero eso es como es mi límite sin actualizar ya yo lo considero como obsoleto o abandonado este por ejemplo tiene unos tres años al menos unos tres años aquí tienes la fecha del último commit que no se actualiza y es el que están recomendando por acá la gente de frame entonces Bueno a mí no me convence intenta instalarlo y tuve problemas con las dependencias de versiones y todo lo demás Por lo tanto tenía que bajar las versiones que tenía actualmente para para poder emplearlo y lógicamente no quiero hacer eso entonces Bueno si quieres emplear este paquete vas a tener seguramente algunos problemas y bueno no sé cómo irá a funcionar a futuro seguirán actualizar Pero al menos al momento en el grado Este vídeo yo lo Considero que está prácticamente abandonado Recuerda que al menos hace tres años y a la fecha es 2023 hace tres años ni siquiera existía el Blue safety entonces bueno puede que tengas problemas por ahí Pero  actualmente igual para analizar un poco dice que trabaja es con Android de momento por lo demás Su uso es lo esperado simplemente aquí detectamos el dispositivo conectado y empezamos a escuchar los botones y bueno el plugin que también vamos a emplear funciona de una manera similar Entonces ya con esto podemos abandonar esta página y seguir aquí avanzando un poquito en mi libro fragmento de mi libro entonces tú puedes hacer una búsqueda en este caso no te recomendaría que lo colocaras flame porque solamente están aparecer esas dos páginas sino directamente en ya que vimos que también podemos emplear varios paquetes o simplemente sintaxis de flutter como tal es decir relativo anteriormente vimos como emplear el de que lo tenemos por aquí ahora está aquí a ver preference que bueno está por aquí en mi menú pero no lo veo que es un paquete exclusivo para flutter pero también lo pudimos emplear sin ningún problema se pudiera decir para Play y aquí tenemos otro que es el que yo encontré es que me parece que mejor pinta tiene decir que mejor luce aunque también la es perfecto se encuentra en desarrollo apenas está la versión que tenemos actualmente al momento en el cual graba este video seguramente ya tuvieras una superior cuando veas este video y se encuentra en desarrollo por lo tanto ya que es algo Bastante Reciente se encuentra en desarrollo la documentación oficial es bastante escasa o decir inexistente al menos actualmente y otro detalle es que bueno la documentación que tenemos aquí también es un poco abstracta es decir lo que es del todo claro cómo funciona Pero bueno para eso es que vamos a hacer el video en el cual vamos a emplear Este plugin Entonces qué es lo que tenemos por acá para explicarte un poco Cómo funciona el plugin si venimos aquí Bueno a ver a la parte de referencia la que tenemos acá por aquí básicamente tenemos es aunque no encuentro todavía la página que me interesa voy a buscarlo un poco creo que era aquí 

Funcionamiento del plugin gamepads

Ok perfecto tenemos estos tres elementos uno es el gamepad controller fíjate que estamos hablando es de clases el gamepad controller hace referencia al control como tal es decir el gamepad el gamepad hace referencia ya a una entrada es decir esta clase Se construye automáticamente por Bueno este paquete como ya vamos a ver unos momentos y los que nos devuelve es un evento un evento de tipo gamepad el cual nuevamente corresponde a la entrada Aquí tenemos información como puede suponer como para ver si entra por acá aunque no era este que quería a ver se encuentra aquí está aquí está mejor el ID ya que podemos tener múltiples controles conectados al dispositivo en Android lo que sea y Bueno pero por aquí vamos a escuchar o vamos a identificarlo mediante gamepad ID es el cero el uno dos tres lo que sea si tiene dos controles vas a tener cero y uno seguramente ya que están que me parece un poco loco pero es la fecha en la cual se disparó para presionar la tecla es decir si lo al momento en el cual se presionó el tipo que esto puede ser o botón o directamente Bueno vamos a verlo ya que Element también está por acá Aunque Bueno te lo va a presentar aquí mejor para no Navegar demasiado puede ser botón o el analógico el analógico hace referencia por ejemplo a los estilos es decir las palancas y también la cruceta los botones serían el resto el por ejemplo en el caso del Xbox sería el botón de aves y x Y esto es lo que nos devuelve por aquí en el en el tipo También tenemos la aquí que es otro elemento muy importante que hace referencia a la tecla en este caso también es como un tipo ya que por ejemplo al menos en el caso que yo probé con este control el del Xbox que te comentaba el del aquí hace referencia.

Por ejemplo si presiono la tecla me vuelve algo así como button-0 y bueno algo así para el resto y también es un elemento muy interesante ya que depende de qué es lo que estés presionando Por ejemplo si presionas un botón Entonces él cuando está presionado coloca el valor de uno y cuando lo liberas coloca el valor de Cero y algo similar al resto de los elementos Pero bueno Esto creo que lo vemos mejor en la práctica así que de momento voy a dejarlo hasta ahí Pero esto es lo que tenemos Entonces cómo se come todo esto volviendo aquí aquí también tenemos el de gamepad que bueno no le colocan una descripción pero a la final también es una clase de utilería que nos permite básicamente armar estas dos y bueno viendo algo de código y para eso lo podemos presentar Dios mío se encontró algo por aquí en la sección de ejemplos bueno Esto no se entiende realmente esto es un ejemplo Bueno no es que no se entiende Pero es bastante abstracto no es lo que yo quiero mostrarte Aunque Bueno lo puedes ejecutar ahí y ves cómo funciona pero no es el ejemplo que yo quiero encontrar por eso que te digo que aquí la documentación es inexistente y un poco difícil de seguir volviendo Aquí esta página a la que es la documentación creo que era la que aparece aquí cuando le damos a preference si está justamente esta por aquí tenemos el de gamepad Que fíjate que podemos interactuar o por aquí Comienza todo esto nos devuelve un listado de los dispositivos Por ejemplo si tenemos un control conectado Entonces no va a devolver una raíz con control si tenemos dos devolvería 2 etcétera por supuesto controles en este caso específico que reconozca el dispositivo específicamente en mi caso mi máquina Windows que tenemos bueno que las que estoy grabando tengo que tener conectado un control a mí en particular me funcionó conectando la Bluetooth pero si no te funciona por Bluetooth puedes conectarlo también por cable Este es el interesante y es el que vamos a emplear Fíjate que simplemente dos líneas de código que es el que dispara los eventos es decir cada vez que presionemos un botón o una cruceta una analógico por aquí se va a ejecutar este método y por aquí vamos a tener información y aquí tenemos el evento el evento que hace referencia hay que te mostrará por acá Bueno voy a volver acá gamepad even con toda la información que te mencionaba antes es lo que tenemos acá aquí te digo que es un poco abstracto porque bueno no lo señalizan bien A mi parecer ni siquiera hacen referencia a esa clase por acá simplemente indican even y ya Entonces hasta cuando haces ahí los puntos de interrupciones no funcionan bien ya vamos a ver eso en detalle pero bueno aquí es lo que tenemos para aquí también si te dice que el evento pero bueno Me parece que está un poco desorganizado esto por lo demás Fíjate que no hace falta registrarlo no hace falta ese no hace falta registrar el dispositivo y nada por el estilo es extremadamente simple extremadamente limpio lo que tenemos que emplear Así que esto es el plugin que vamos a emplear específicamente nos interesa es esta función:

Gamepads.events.listen((GamepadEvent event) {
});

Pero bueno vamos a practicar un poquito más y también vamos a ver que nos devuelve esta función entonces finalmente Para instalarlo para ir saliendo de esto es lo típico colocamos gamepad Bueno ya sea que ejecute ese Comando lo que sea yo voy a regresar acá colocó un punto importante es que este plugin no funciona para móviles ni tampoco web por lo tanto no lo puedes emplear por ahí en principio entiendo que funciona para PC en este caso Windows no lo he probado en mates pero que también funcione más y por supuesto Linux Pero bueno ahí ese es el que tenemos a nuestra disposición al menos de momento ya que realmente hay muy pocos paquetes que funcionan con gamepad específicos para por supuesto para frame solamente existe o al menos que yo conozca el que te presente inicialmente así que por lo demás poco más que decir nuevamente funciona para Windows y creo que para más Linux no lo he probado el paquete es muy sencillo simplemente aquí tenemos un método para obtener los controles conectados otros para escuchar las pulsaciones a los analógicos o los botones Este es el evento que nos describe y poco más que decir instalarlo y ya con esto podemos continuar al siguiente video.

Por supuesto si te interesa hacer esta implementación tienes que tener Sí o sí un control de videojuegos que te reconozca tu PC contigo ya que si no lo tienes no vas a poder probar la implementación Ok por aquí tenemos nuestro videojuego también puedes ver que active la cámara en este caso está enfocando el control que yo voy a emplear para hacer esta prueba como te comentaba es un control de Xbox s te debería de funcionar cualquier otro pero bueno si eres Gamer o has jugado algunos videojuegos en PC debe saber que inclusive para juegos más robustos es decir empleando tecnologías más robustos inclusive existen problemas con los controles por lo tanto bueno no esperes que por aquí vaya a ser diferente entonces Bueno aquí esto importante si vives con un familiar o algo por el estilo una novia o algo recuerda decirle que me estás trabajando que tengas aquí un control de PlayStation o lo que sea en tus manos bueno dicho esto Ahora sí vamos a comenzar como te indicaba la implementación extremadamente simple Aquí también recuerda tener colocado el plugin que se haya instalado

dependencies:
  flutter:
    sdk: flutter
  ***
  gamepads:

Entonces vamos a trabajar específicamente aquí en el de Player componente en el evento llamado onload que lo tenemos en alguna parte sino en el init Bueno aquí lo tenemos perfecto voy a colocarlo por acá arriba realmente porque importa donde lo quieras colocar Pero bueno ya aquí que tenemos un así lo podemos aprovechar Entonces por aquí lo que vamos a hacer es ver qué dispositivos tenemos conectados para eso Aquí voy a crear una variable llamada kimbax que es igual una wave ya que bueno como puede suponer es una operación asíncrona a gamepad aquí tenemos a paquete sería este el de gamepad gamepads punto listo y es así de simple ya con esto tenemos acceso a todos los controles que estén conectados esto nuevamente es una prueba todavía no vamos a implementar nada por aquí lo voy a imprimir a ver que nos imprime para ver si es similar a lo que mostraba la documentación oficial y por aquí ya de una Para aprovechar el tiempo vamos a definir nuestro gamepad Esto es para el evento escuchador punto viste y por aquí colocamos el sería el aquí a mí me gusta colocarle el tipado para que quede claro voy a llamar 9 en la documentación oficial solamente aparece así Pero nuevamente a mí me gusta colocarlo con el tipo esto por cierto es una función es decir el argumento es una función Así que lo colocamos dentro de unos paréntesis y por aquí en lo que tenemos entonces aquí podemos colocar un print o algo por el estilo y Bueno un poco más que decir aquí también me gustaría siempre me gusta para las impresiones colocar algo llamativo para poder ubicarme mejor coloco esto por acá y esto también por acá Aunque en principio Recuerda que este evento ya que es un evento tiene disponible todo esto lo que te comentaba ahí el dispositivo la fecha la cual existe la pulsación el tipo si es analógico o botón el botón como tal que le coloca Hay una tipificación no sé por qué no emplear en un enum Pero bueno lo dejaron así y aquí en valor si guardamos voy a aprender el control voy a dejarlo aquí presionado ahí prendió voy a esperar unos momentos A ver qué pasa y voy a actualizar aquí la aplicación mira que lo que tenemos en este caso yo lo tengo conectado por bluetooth a mi PC y aquí lo toma perfectamente aquí aparece la instancia del control conectada si yo lo apago que bueno para pagar esto es un dilema voy a ver si quiere Apagar si no le quito la pila ahí apagó y recargo la aplicación a veces aparece porque bueno tarda un poco en aquí no lo tiene en detectar que no está presente entonces puedes ver que este es el control que está funcionando aquí puedes ver que también este evento funciona un poco extraño ya que cuando lo reconoce entonces hay veces que se ejecuta también y te coloca este montón de impresiones esto Recuerda que hace referencia un botón pulsado aunque yo no puse ninguno la sección del del medio que no creo que lo registre pero bueno a veces pasa esto no lo entiendo muy bien por qué pero no importa eso realmente entonces aquí nuevamente tenemos el control de gamepad controller que era una de las tres clases principales que te comentaba que teníamos bueno que tenemos disponibles en este paquete entonces realmente con esto no vamos a hacer nada pero por ejemplo por aquí puedes preguntar por elementos como el ID entonces Bueno recuerda que esto es una lista Así que pregunto por la posición 0 aquí tenemos el gamepad controller y aquí tenemos el ID aquí me dice que es un control de Xbox tal cual puedes ver y bueno alguna información adicional pero lo importante aquí sería Lady y el nombre por si lo quieres colocar en alguna parte del juego ahí lo tienes entonces voy a aquí a recargar todo aquí en este punto tienes que tener activa la ventana es decir enfoco porque si presionas aquí el control no va a reconocer Nada aquí

0 y 1 al presionar los botones

Yo estoy presionando tal cual puedes ver y no pasa nada Ya esto en este punto lo puedes comentar Para que no haga ruido y puedes ver que no funciona si no tienes activa la ventana Así que colocas aquí la ventana y aquí vas a ver que aparece fíjate cuando lo dejo presionado coloca el valor de uno Bueno aquí la cerró porque perdí el foco cuando presiono un botón coloca el valor de uno aquí lo va a liberar y coloca el valor de Cero y lo mismo para el resto aquí yo presione y fíjate que es botón cero bueno Dios mío que maníaco hacer esto el botón cero para este que es el B el botón 1 lo mismo uno activo cero desactivado Este es el botón 2 y bueno Esto lo tienes que mapear tú de decir No sé si esto cambie según el control que estés empleando o si lo van a cambiar a futuro etcétera tienes que tener presente estos valores los joysticks son un poquito bueno no decir que esté mal implementado porque no lo creo que esté pero bastante complejo mira que apenas lo muevo mira que aquí tenemos valores si lo muevo bastante aquí puedes ver cómo cambian los valores y aquí también cambia el nombre del botón y lo mismo para el otro bueno Esto es interesante porque lógicamente menos es el movimiento entonces más chiquito es el valor Mientras más largo es el movimiento como en este caso estoy pegado al extremo Debería ser mayor el valor tal cual puedes ver por lo demás lo mismo tenemos para el resto de los botones este serían para el de estar y el de Select tenemos valores al igual que por aquí lo que tenemos atrás ahí los tenemos y 

Cruceta, valores variables

La cruceta también es interesante mira que si aquí le colocó para arriba tenemos el valor de cero si aquí le coloco para es que lo tengo al revés en este caso este sería la derecha sería 9000 si lo coloco y right al mismo tiempo mira que tenemos 4500 si lo coloco abajo tenemos 18000 es decir creo que te diste cuenta pero aquí tenemos un valor que hace una similitud con un radio de 360 grados nuevamente o sería cero Button sería 18000 by sería 9000 y para left sería 27 Y nuevamente left sería bueno a ver 31.500 entonces esos valores los Tenemos que tener presentes para cuando queramos Escuchar aquí estos botones tal cual puedes ver cuál es la idea Bueno básicamente poder mover aquí el Player en este caso lo va a mover por el teclado o como quiera podemos ver que solamente se desplaza de manera recta Es decir para arriba para abajo derecha e izquierda él si tú utilizas el teclado no se desplaza así lateralmente en este caso si se desplaza lateralmente porque estamos utilizando un…

Joystick

Joystick virtual pero para la implementación que hicimos para el teclado no lo hacen Claro está aquí tú pudieras implementar esto como tú quieras pero bueno aquí lo que estoy indicando que es lo que tenemos acá por ejemplo para la cruceta que es lo que nosotros vamos a emplear para mover este Player inclusive podemos detectar aquí movimiento inclinados Por decirlo de alguna manera es decir presionando op y left o up y right al mismo tiempo o botón right al mismo tiempo por lo tanto ahí pudiera aprovecharlo para moverlo de manera inclinada yo no lo voy a hacer así la implementación porque Sencillamente no es lo que hicimos por acá Recuerda que el movimiento para el evento de teclado sería lo que tenemos por aquí right por lo tanto aquí tuvieras que implementar otra lógica de la cual coloques ahí los inclinados es decir y bueno pero bueno no lo quiero hacer porque simplemente quiero aprovechar el código que tenemos actualmente para este pequeño proyecto para esta pequeña adaptación así que bueno esto sería prácticamente todo En definitiva una vez instalado el plugin coloca aquí el evento escuchador justamente aquí en el Player componentes tal cual lo tenemos aquí tenemos el Bueno estamos imprimiendo el evento Entonces por aquí hace algunas pruebas identifica tú cuáles son los botones que tú quieres emplear para lograr el movimiento en mi caso en particular va a ser el botón a para hacer la rotación y la cruceta para hacer el movimiento el resto no me interesa pero bueno siéntete libre de terminar de adaptarlo Por ejemplo si presionas aquí están que le colocas aquí pausa o despliegues algún menú esas pequeñas adaptaciones siéntete libre de hacerlas tú como mejor consideres así que poco más que decir antes de terminar si me gustaría colocar aquí un punto de interrupción aunque no me hace caso voy a aquí a recargar ahí está y bueno si lo evalúas por acá vas a ver que te devuelve Esto entonces ahí no tenemos información pero en fin recuerda aquí también importante que puedes colocar por ejemplo de gamepad ID ya esto te lo tomo automáticamente gracias a la tipificación que colocamos acá si no la colocas entonces Bueno aquí lo reconoció no sé por qué pero bueno lo más seguro que no te aparezca nada de esto si simplemente colocas aunque bueno todo depende de la versión de que estés empleando pero bueno era para que también lo tuvieras presente aquí conozco ID guardamos voy a quitar este punto de interrupción voy a recargar nuevamente aquí la pantalla activa y presionas y ahí lo tienes nuevamente en resumen prueba aquí obtener el estado simplemente como ejercicio simplemente listener aquí puedes colocar una propiedad u otra pues colocar lo que tú quieras ventana activa y empieza a presionar aquí las teclas bueno los botones para que veas qué es lo que aparece por acá también siéntete libre colocar el resto de los valores que sería algo como esto para que aquí obtengas más información aquí ya yo lo tenía aquí una chuleta Si reiniciamos por acá presiono aquí la cruceta vas a ver que él dice que es de tipo analógico si presiona un botón es de tipo botón y Bueno aquí nuevamente los valores que los valores los puedes emplear dependiendo del tipo b botón o analógico que estés empleando como puedes ver nuevamente para los botones es 0 y 1 para la cruceta es algo un poco más interesante que podemos aprovechar también para saber cuál fue la inclinación O cuál fue exactamente lo que puso aquí por cierto también trabaja de manera similar cuando lo pulsas mantiene el valor y cuando lo liberas pone otro valor que realmente no sé qué hace referencia Pero bueno lo que aparece ahí como te digo nada de esto lo indica la documentación oficial son cosas que tenemos que hacer son pruebas que tenemos que hacer.

Así que nuevamente en resumen instala el paquete coloca listener pues colocar estos valores para que sepas exactamente cómo funciona pulse algunos botones la nota en caso de que tengas una definición diferente a la mía Cuáles son los botones el nombre de los botones y bueno por lo demás poco más que decir una vez hecho esto podemos hacer la implementación muy pero muy sencillo pero eso será tema del siguiente video OK ahora sí vamos a realizar la implementación que vemos aquí en que tenemos un listing para escuchar sobre nuestro juego:

Gamepads.events.listen((GamepadEvent event) {
  
});

Las teclas o los botones de nuestro mando y recordemos que tenemos ahora que mapearlo es decir el botón cero por ejemplo cuando tiene el valor de uno que es cuando lo presiono queremos que rote y lo mismo con el resto de los botones y analógicos o bueno yo hago Simplemente digo botones para todo el mando pero bueno defina lo como tú quieras recuerda que aquí en el plugin dice analógicos para los que devuelven un valor distinto a cero o cero y uno y los botones serían 0 y 1 nuevamente 1 cuando está presionado y cero cuando está liberado Ok una cosita también interesante es que por alguna razón el plugin me inhabilitó los botones del bueno los eventos para escuchar las teclas de teclado Entonces no lo puedo mover con el teclado en la documentación oficial me encontré nada entonces Supongo que es un pequeño Boot de igual manera Recuerda que estamos realizando experimentos y poco más entonces Bueno hay varias formas de hacerlo por ejemplo si no tenemos controles Entonces no ejecuta esto o habilitarlo desde el menú Hay muchas formas de hacerlo aquí como te digo estamos realizando solo los experimentos pero si es una cuestión del paquete me parece Porque cuando el ejecuta un web si me funciona otra vez el teclado era bueno era para decirlo en caso de que también te esté ocurriendo lo mismo que espero que lo solucionen a futuro en fin dicho esto Ahora sí vamos a comenzar teniendo claro todo esto voy a comentarlo y lo único que tenemos que hacer aquí es realizar las condiciones recuerda que en caso de que varíen ya que solamente tengo control y de este tipo por lo tanto voy a colocar son los valores que a mí me aparecen pero si a ti te aparecen otros tienes que colocar los tuyos en fin colocó aquí para obtener el nombre que le haya colocado a Ese botón por aquí entonces queremos en el botón cero pero no solamente esto sino el Evening sea igual igual a uno punto cero o simplemente uno si este es el caso entonces aquí aplicamos el rotate de momento lo dejo así para bueno ayudarme un poco con los mensajes y ahorita colocamos la implementación real Entonces el siguiente caso sería el voy a duplicar esto varias veces ya que es más o menos lo mismo el siguiente caso el evento ya sería para la cruceta o el depata también le llaman Entonces ya aquí no es Plutón Así que voy a seleccionarlo sino sería el deploy a ver cuántos tengo uno dos tres bueno va a seleccionarlos todos le coloco y aquí sí variamos el valor según lo que queramos seleccionar Así que para el primero que sería el de Ok como indicamos colocamos 0 y aquí coloco, recuerda que es 360 grados Pero bueno algo similar una similitud que hicieron por aquí el siguiente sería el raid simplemente lo va a colocar por dejarlo aquí pero realmente no lo vamos a emplear como comentamos antes que sería de 4500 el cual sería el all right y aquí también lo coloco el siguiente sería ya directamente el write por write el siguiente sería el de 13.500 que sería el de button write ya este sería el de 18000 Y bueno ya casi estamos el siguiente sería el de 22.500 que sería el de fútbol el siguiente sería el de Left 27.000 y el siguiente y último Ah no Ya estamos bien el siguiente sería top left que sería 31.500 no hace falta más este sería Aquí también el comentario y ahí estamos voy a recargar y pruebo bueno traigo aquí el juego ahí lo tenemos rotate voy a comenzar arriba inclinado por right button left Ok hay uno que no me lo está tomando hasta el left el del led no lo está tomando a ver aquí es Oh disculpa que tengo un pequeño mareo voy a recargar ahí está perfecto entonces funciona correctamente lo que hacemos ahora es muy simple hacemos aquí el llamado correspondiente aquí rotamos  y aquí lo que tenemos que hacer es emplear el momentive es igual a ventate punto este sería el vamos a ver ahí está:

Gamepads.events.listen((GamepadEvent event) {

    if (event.key == 'button-0' && event.value == 1.0) {
      print('jump');
    } else if (event.key == 'pov' && event.value == 0.0) {
      // up
      print('up');
    } else if (event.key == 'pov' && event.value == 4500.0) {
      // up - right
      print('up - right');
    } else if (event.key == 'pov' && event.value == 9000.0) {
      // right
      print('right');
    } else if (event.key == 'pov' && event.value == 13500.0) {
      // buttom right
      print('buttom right');
    } else if (event.key == 'pov' && event.value == 18000.0) {
      // buttom
      print('buttom');
    } else if (event.key == 'pov' && event.value == 22500.0) {
      // buttom left
      print('buttom left');
    } else if (event.key == 'pov' && event.value == 27000.0) {
      // left
      print('left');
    } else if (event.key == 'pov' && event.value == 31500.0) {
      // top left
      print('top left');
    }
  });

OK vamos con los siguientes nuevamente este no lo voy a emplear lo dejo Ahí de referencia siéntete libre de adaptarlo este Sería para right este sería para el botón o el down no sé cómo le coloque este Sería para el left voy a comentar todo esto y ya estamos Ok claro Aquí está el problema en que siempre quedamos en movimiento cosas que también sería interesante implementar juego así o al menos un nivel para un poquito más lento pudiera hacerlo pero ahí bueno Claro porque siempre estamos dejando aquí el momentive por lo tanto siempre estamos indicando que se está moviendo y ahí el problema aquí finalmente pudiéramos colocar ya este es el del hasta el doctor bueno pudiéramos colocar uno dos en el cual sería si presionamos cualquier otra cosa vamos a ver qué tal nos va así aquí colocamos igual a momentive punto ahí realmente cuando estamos presionando a cualquier botón estamos indicando que se ejecute este Pero bueno ya queda en Estados Unidos también pudieras preguntar aquí porque es lo que nos interesa es realmente esto a excepción del primero Claro está pero pudiéramos colocar lo va a dejar de referencia para que quede claro por si quieres implementar otro botón por si tienes algún conflicto pero lo que nos interesa es preguntar aquí por el cero deben evaluarlo es cero y que sea de tipo esto me parece que debería ser Exactamente igual que no no claro no va a funcionar porque este es el top aquí me enredé que fue con el del botón pero no está bien así cualquier cosa recuerda dejar este condicional de último si quieres colocar más condiciones las colocas arriba y este sería el último obviamente porque se las el caso hace como el en el switch y ahí tenemos la movilidad empleando el gamepad y ya con esto terminamos la implementación del gamepad para nuestro juego.

- Andrés Cruz

In english

Andrés Cruz

Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz En Udemy

Acepto recibir anuncios de interes sobre este Blog.