Reflex Game en Arduino. Crea desde cero tu propio juego.
Cómo hacer un juego en Arduino con botones led, un monitor y un altavoz.
Siguiendo los pasos de este post podrás crear un juego que mida la capacidad de reacción del jugador poniendo a prueba sus reflejos. Tanto el funcionamiento del juego como las reglas son simples, sin embargo, existen varios niveles de dificultad que puedes ir incluyendo poco a poco . Este juego en concreto, consiste en diferentes estímulos visuales, en forma de pulsadores, al que el jugador debe reaccionar y presionar sin equivocarse en el menor tiempo posible.
Sobre esa base, incrementamos la complejidad incluyendo dos dispositivos de salida básicos para que el jugador reciba la retroalimentación necesaria tanto para comenzar la partida como para conocer el estado de esta, esto es un monitor o pantalla LCD y un altavoz o piezo buzzer pasivo. Además, a medida que se consolida la parte hardware del proyecto, se pueden incluir nuevos modos de juego de forma que aumente la experiencia de juego del usuario
Puedes ver el vídeo que hemos prepardo y engloba las 3 partes fundamentales (Hardware, Software y Funcionamiento) para que tomes una visión global. Después del vídeo encontraras los pasos por escrito de cada una de las etapas.
Lista de componentes necesarios
A continuación tienes un checklist con los componentes y materiales necesarios con un prespuesto de aproximadamente 50€:
Componente |
Piezo buzzer pasivo |
Cables para protoboard |
Pulsadores arcade con led integrado de 5V |
Pistola de pegamento caliente mini con recambios |
Terminal faston hembra para cables |
Termorretractil para cables |
Caja de plástico |
Monitor LCD interfaz I2C de 16×2 |
Broca especial circular |
Pintura en spray |
Placa Arduino 1 y protoboard |
Esquema de conexiones
Hardware
Te contaremos el proceso desde nuestra perspectiva. Una vez hemos obtenido los componentes, el primer paso que realizamos fue comprobar el funcionamiento de los botones, tanto en su parte led como en su respuesta de pulsación. Tras haber hecho esto tuvimos que preparar el cable para que quedase completamente acoplado a los botones, para ello utilizamos terminales faston hembra en cada uno de los extremos de los cables que iban conectados a los botones y los recubrimos con termorretractil de manera que quedasen sellados.
Tras esto pasamos a comprobar el correcto funcionamiento de la pantalla lcd, momento en el cual nos encontramos con el primer problema. A la hora de comprar la pantalla lcd y la interfaz I2C lo hicimos por separado, por lo que en el momento de acoplar ambas partes nos dimos cuenta de que el contacto que había entre ambas no era bueno y, por tanto, no mostraba correctamente por pantalla. La única forma de que funcionase correctamente era sujetarlo fuertemente mientras cargábamos el código de prueba en Arduino.
Buscamos distintas soluciones:
- La primera de ellas fue conectar la pantalla y la interfaz mediante cables, lo cual era muy poco práctico. Aun así, esta solución no nos sirvió, pues la conexión entre ambas seguía sin ser estable y daba fallos.
- La segunda fue intentar soldar dichos cables a la pantalla lcd, de manera que quedasen fijos y no diesen problemas de inestabilidad. Esta solución tampoco fue la definitiva pues, aunque sabíamos el riesgo de intentar soldar nosotros mismos los cables queríamos gastar esa posibilidad y probar antes de buscar otra alternativa.
- La última solución, y desde luego la más efectiva, fue comprar una nueva pantalla lcd que venía con la interfaz I2C perfectamente acoplada y soldada, la cual tras realizar diversas pruebas no nos dio ningún problema y fue la solución definitiva.
A la hora de conectar el altavoz para realizar también las respectivas pruebas con el tuvimos que soldar el cable que iba conectado a este, pues con la conexión que tenía era la única forma.
Para la caja del juego nuestra principal idea era usar metacrilato lo cual, tras varias consultas en diferentes tiendas, no pudo ser posible debido al elevado precio de este (130€ aproximadamente). Como segunda alternativa usamos una caja de plástico duro que fuese lo suficientemente fuerte como para aguantar las pulsaciones sin ceder. Compramos varios tamaños y tipos de cajas y usamos la que mejor se adaptaba a lo que necesitábamos.
Para la preparación de esta hicimos un boceto de esta teniendo en cuenta las dimensiones de la pantalla y el diámetro de los botones de manera que estos se pudiesen encajar y que, además, quedasen todos a la misma distancia y el resultado final de la caja fuese lo más profesional posible. Aquí nos encontramos con el segundo problema, pues no fue nada fácil encontrar una herramienta adecuada con la que hacer los agujeros de forma correcta y que no se partiese el plástico en el proceso. Tras mirar diferentes alternativas dimos con una broca especial circular del tamaño del diámetro de nuestros botones que era apta para madera, plástico y otros materiales.
A la hora de realizar los agujeros hicimos una primera prueba que salió mal, pues al ejercer presión mientras la broca giraba, el plástico cedió y se partió. Una vez aprendido donde estaba el fallo comenzamos a hacer los demás agujeros, los cuales quedaron perfectos, teniendo únicamente que lijar las pequeñas imperfecciones. Para el hueco de la pantalla hicimos otro agujero y a partir de ahí con una lija le fuimos dando forma hasta que quedase un rectángulo del tamaño que necesitábamos. Por último, hicimos un agujero más para la salida del cable de alimentación que va conectado a Arduino, así como uno para el cable del altavoz.
Tras tener todos los componentes preparados procedimos a colocar los botones en la caja, así como a conectar los cables correspondientes en cada uno de ellos, conectamos también el altavoz y, por último, la pantalla. Una vez que teníamos todos los componentes conectados correctamente a Arduino comenzamos con la codificación.
Software
Primero de todo, para codificar el juego en el IDE de Arduino, se necesitan 2 librerías, Wire.h y LiquidCrystal_I2C.h ambas referentes a la pantalla LCD.
Declaramos una variable lcd que nos permite controlar el monitor, 5 constantes numéricas que recojan el valor de cada botón y de igual manera otras 5 para el valor del LED, dos constantes para saber si un botón está pulsado o no, una variable para el altavoz, diferentes variables para calcular los tiempos, los records actuales y un array con las opciones del menú.
En la función setup() simplemente se inicializa el LCD, los botones como entrada, sus LEDs como salida y el altavoz como salida.
El loop() alberga toda la funcionalidad que nos permite interactuar con el jugador. A grandes rasgos el loop se encarga de mostrar en el monitor el menú de selección del juego, desplazando hacia arriba con el botón verde y hacia abajo con el rojo, esperando a que el jugador pulse el botón blanco el cual confirma la selección. El contador “modo” sumará 1 si sube y restará 1 se baja, luego dependiendo de en que punto se encuentre, se inicia una cuenta regresiva de 3 segundos y se llama a la función que selecciona el modo de juego pasándole el contador.
Por último, se describe en términos generales el comportamiento esperado de las funciones auxiliares empleadas:
- modoDeJuego: ramas if-else sencillas para determinar si se trata del modo por dificultad, cantidad o tiempo.
- modoDificultad: existen 3 niveles de dificultad en función del tiempo que tardan en encederse y apagarse el LED del botón a pulsar, siendo de 1 segundo el más fácil y medio segundo el más difícil. Hasta que el contador de botones pulsados sea menor que 25, se encenderán botones aleatoriamente permitiendo la repetición de este. Si en el tiempo que permanece encendido al jugador no le da tiempo a pulsarlo, automáticamente pierde la partida. Son necesarias 5 ramas if-else por cada botón al cual se le asigna un valor numérico previamente. 0 amarillo, 1 rojo, 2 azul, 3 verde y 4 blanco. Con ello se consigue encender ese botón en concreto y se comprueba que se pulsa ese mismo a tiempo.
- modoCantidad: este modo se codifica de forma muy similar al anterior, la principal diferencia reside en que en vez de tener una variable con el tiempo límite que tiempo el jugador para pulsar el botón, este permanece encendido, se realiza el bucle hasta que se hayan pulsado 20 o 50 depende del modo y se comprueba si es un record o no.
- modoTiempo: para codificar el modo que únicamente tiene en cuenta el número de botones que es capaz de pulsar en 30 o 60 segundos, es necesario ir calculando en cada iteración del bucle while, si el tiempo sigue siendo válido para realizar las operaciones de encendido y comprobación como en los modos anteriores. De igual manera se imprime en el monitor una cuenta regresiva con el tiempo restante.
- nuevoRecord: dadas las variables globales que fijan un record anterior, y los valores recibidos por parámetro de las funciones que implementan los modos de dificultad, se comprueba si la partida actual supera el record anterior. En concreto, esta función es complementaria al modo por cantidad, ya que, dado el tiempoActual si este es menor al anterior, se llama a esta función que felicita por pantalla al jugador, enciende y apaga los botones de forma intermitente y actualiza el valor con el nuevo record.
- nuevoRecordPulsaciones: funciona de la misma forma que el anterior a diferencia de sirve de función auxiliar para el modo por tiempo, es decir, el record en vez de medirse en segundos, se mide en número de pulsaciones, si es mayor al anterior, se produce un nuevo record y se producen las mismas operaciones que en nuevoRecord.
- juegoDificultadTerminado: para el modo por cantidad y por tiempo, se tiene como pantalla final si ha superado el record o no, en cambio para los modos por dificultad es suficiente con mostrarle al jugador si completó el nivel.
- juegoPerdido: enciende todos los botones, muestra por pantalla GAME OVER y el altavoz reproduce un sonido de partida perdida.
- encenderBotones: coloca las señales de todos los botones a HIGH.
- apagarBotones: sitúa las señales de todos los botones a LOW.
Funcionamiento
Entre los casos de uso del proyecto esperados se incluyen los siguientes:
Modo Fácil
El usuario elige en el menú la partida de modo fácil, la cual consiste en el modo básico de juego en el que el usuario ha de pulsar los botones tan rápido como se enciendan, tratando de acertar el mayor número posible. Cuando el jugador falla la partida termina y se muestra por pantalla el número de pulsaciones y el record actual.
Modo medio
Este modo al igual que el anterior consiste en pulsar la mayor cantidad de botones posibles haciendo uso de los reflejos, pero esta vez un poco más rápido que en el modo fácil.
Modo difícil
Este modo tiene el mismo mecanismo que los dos anteriores, pero aumentando la dificultad.
Modo mejor tiempo de 25 pulsaciones
Se trata de un modo de juego diferente a los anteriores en el que el objetivo es conseguir pulsar el mayor número de botones posible dentro del tiempo de 25 segundos, por lo que el jugador debe ser rápido para conseguirlo. Una vez que termina el tiempo la partida termina y se muestra por pantalla el resultado final y el record actual.
Modo mejor tiempo de 50 pulsaciones
Funciona de la misma forma que el modo anterior, pero el tiempo en lugar de ser 25 segundos son 50.
Modo mejor resultado de x tiempo
Este tipo de partida es igual que los dos anteriores, pero en este caso es el usuario el que decide cuánto tiempo quiere que dure la partida.