Tabla de contenido:

Arduino - Piano Tiles: 16 pasos (con imágenes)
Arduino - Piano Tiles: 16 pasos (con imágenes)

Video: Arduino - Piano Tiles: 16 pasos (con imágenes)

Video: Arduino - Piano Tiles: 16 pasos (con imágenes)
Video: Mini juego de plataformas con Arduino y pantalla LCD 16x2 caracteres 2024, Mes de julio
Anonim
Arduino - Piano Tiles
Arduino - Piano Tiles

Hola gente de Internet, Esto va a ser sobre cómo hacer lo que DEFINITIVAMENTE no es una estafa de un juego móvil en un arduino uno r3.

así que para empezar, necesitarás todas las piezas, ¡que son las siguientes! 1x Arduino Uno r3 ($ 42)

2x protector de teclado LCD ($ 19 cada uno)

5x botones

5 resistencias de 220Ω

28x cables

Muy bien, una vez que tenga todas las partes, ¡es hora de comenzar!

Paso 1: cableado

Alambrado
Alambrado
Alambrado
Alambrado
Alambrado
Alambrado

Comience conectando su arduino y amigos como se muestra en el diagrama, Asegúrese de que los botones estén vinculados correctamente, con las ranuras A0-4 en el lado del suelo de los rieles de los botones, o el arduino pensará que los botones se mantienen presionados constantemente en lugar de solo presionarlos.

Paso 2: declaraciones de declaración

Todo el código aquí debe ir antes de su configuración de vacío y bucle de vacío, esto se debe a que todas estas variables y objetos se utilizan en varias de las funciones que configuraremos.

Empiece poniendo:

#incluir

en la parte superior de su código, esto le dice al arduino que use la biblioteca "LiquidCrystal.h" y las funciones que son parte de ella.

El siguiente paso es definir los pines que estamos usando para nuestros botones colocando este código debajo de nuestro #include:

#define btnEnter A0 # define btn1 15 #define btn2 16 #define btn3 17 #define btn4 18

Definimos los términos btnEnter y btn1 a btn 4 para facilitar la lectura del código, o cambiarlo si es necesario. Significa que cuando escribimos btn1, el arduino sabrá que de hecho nos referimos al botón 15. Aunque estamos llamando a los puertos 15, 16, 17 y 18, están etiquetados en el arduino como A1 A2 A3 y A4, esto se debe a que son puertos que se usan específicamente para entradas analógicas, aunque solo los estamos usando para entradas digitales.

A continuación, crearemos los objetos que controlarán las pantallas de cristal líquido. Para hacer esto, coloque este código debajo de nuestras definiciones

LiquidCrystal lcdLeft (8, 9, 12, 10, 11, 13); LiquidCrystal lcdRight (2, 3, 4, 5, 6, 7);

Lo que hace es decirle al arduino que cuando llamamos a lcdLeft o lcdRight nos estamos refiriendo a un objeto LiquidCrystal. Los números en los corchetes adjuntos le dicen al arduino qué puertos debe usar el objeto para enviar mensajes a la pantalla LCD cuando usamos sus funciones.

Ahora necesitamos declarar las variables colocando el siguiente bit de código debajo de las declaraciones del objeto:

// estas variables son opciones que puede cambiar - números más altos = velocidad de juego más rápida upint intGameSpeedEasy = 10; int intGameSpeedMedium = 25; int intGameSpeedHard = 80;

// configurar variables para el gameboolean bolPlay; // rastrea si el jugador int intScore; // rastrea la puntuación del jugador int intDiff; // solo una cosa estética para decir en qué dificultad se encuentra el juego // configurar variables para input int intEnter; // rastrea si el usuario presiona el botón enter int intInput; // rastrea qué botones presiona el usuario boolean bolTilePressed; // asegúrese de que el jugador no presione accidentalmente un botón 5x y pierda // configure las variables para turn int intTick; // cuenta milies (por ciclo) hasta intDelay int intDelay; // el tiempo que el programa espera hasta el próximo turno en millis int intGameSpeed; // un poco de opciones de depuración boolean bolSerialBoard; // cuando sea verdadero imprimirá la placa en el monitor serial

Declaramos una variable indicando el tipo de datos y luego el nombre de la variable, ej. int thisIsAnInteger

Las variables booleanas, como bolSerialBoard y bolPlay solo pueden tener uno de dos valores, verdadero o falso.

La variable entera (int) como intScore e intInput puede tomar números enteros como valores, como 1, 5 o 100.

Algunos otros tipos de datos notables que no estamos usando aquí son una cadena, que es un fragmento de texto, y un flotante, que es un número decimal.

Cada una de las variables aquí se usa en varios lugares diferentes por el programa, aquí hay una sinopsis de lo que hace cada una

bolPlay le dice al programa si el menú debe mostrarse o si el juego real debe estar ejecutándose.

intScore rastrea la puntuación del jugador cuando golpea las fichas, intDiff se usa en el menú principal para decirle al programa qué fragmento de texto imprimir en la pantalla LCD, intEnter se usa para decirle al programa si se presiona el botón Enter (más a la izquierda), intInput se usa para decirle al programa cuál de los otros 4 botones se presiona.

bolTilePressed se utiliza para asegurarse de que el programa solo se lea cuando se presione el botón y no cuando se mantenga presionado.

intGameSpeed, intGameSpeedEasy, intGameSpeedMedium e intGameSpeedHard se utilizan para controlar la rapidez con la que el juego debe acelerarse en función de la dificultad seleccionada.

intTick e intDelay se utilizan para evitar que el programa mueva la placa cada vez que se repite.

bolSerialBoard se usa para permitirle hacer que el programa envíe la placa al monitor serial del arduino como una serie de números para propósitos de prueba.

Finalmente, es hora de declarar nuestro tablero como una matriz usando este código:

// configurar el juego arrayint arrGame [16] [4] = {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}};

Una matriz es una matriz en cualquier punto en el que se puede llamar para matemáticas o cambiar.

Su código ahora debería verse así;

// incluir bibliotecas # incluir

// estas variables son opciones que puedes cambiar - números más altos = juego más rápido acelerado

int intGameSpeedEasy = 10; int intGameSpeedMedium = 25; int intGameSpeedHard = 80;

// Definir pines

#define btnEnter A0 #define btn1 15 #define btn2 16 #define btn3 17 #define btn4 18

// crea objetos LCD (n, ~, n, ~, ~, n)

LiquidCrystal lcdLeft (8, 9, 12, 10, 11, 13); LiquidCrystal lcdRight (2, 3, 4, 5, 6, 7);

// configurar la matriz del juego

int arrGame [16] [4] = {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}};

// configurar variables para el juego

boolean bolPlay; // rastrea si el jugador int intScore; // rastrea la puntuación del jugador int intDiff; // solo una cosa estética para decir en qué dificultad se encuentra el juego

// configurar variables para entrada

int intEnter; // rastrea si el usuario presiona el botón enter int intInput; // rastrea qué botones presiona el usuario boolean bolTilePressed; // asegúrese de que el jugador no presione accidentalmente un botón 5 veces y pierda

// configurar variables para el turno

int intTick; // cuenta milies (por ciclo) hasta intDelay int intDelay; // el tiempo que el programa espera hasta el próximo turno en milis int intGameSpeed;

// un poco de opciones de depuración

boolean bolSerialBoard; // cuando sea verdadero imprimirá la placa en el monitor serial

Paso 3: la función de configuración

El ciclo de configuración es una función que el arduino lee solo una vez cuando se inicia inicialmente.

En el ciclo de configuración, solo establecemos los valores de algunas de nuestras variables porque, en lugar de establecer un valor al declararlas, lo hacemos aquí.

Empiece por poner este código en su configuración nula.

bolPlay = falso; intScore = 0; intTick = 0; intDelay = 1000; intDiff = 1; intGameSpeed = intGameSpeedMedium;

Cada línea es simplemente establecer una variable en un valor.

bolPlay se establece en false para que el juego no comience a reproducirse.

intScore se establece en 0, porque, naturalmente, su puntuación comienza en 0.

intTick comienza en 0 porque el programa actualmente no cuenta nada.

intDelay se establece en 1000 porque esa es la velocidad a la que comienzan los mosaicos.

intDiff es solo una cosa ascética para que el programa sepa qué escribir para la dificultad del juego.

intGameSpeed se establece en lo que sea intGameSpeedMedium, lo que significa que se establece en la dificultad media.

A continuación, coloque este código en la configuración nula debajo del código que acaba de ingresar.

lcdLeft.begin (16, 2); lcdRight.begin (16, 2);

Serial.begin (9600);

Esto le dice al arduino que comience a comunicarse con la computadora a través del monitor en serie (visible al hacer clic en el botón en la parte superior derecha del IDE de arduino).

¡Su configuración de vacío ahora debería verse así!

configuración vacía () {Serial.begin (9600); // iniciar el monitor serial // configurar las variables bolPlay = false; intScore = 0; intTick = 0; intDelay = 1000; intDiff = 1; intGameSpeed = intGameSpeedMedium; // comienza lcdLeft.begin de lcd (16, 2); lcdRight.begin (16, 2); }

Paso 4: la función de bucle

La función de bucle es ejecutada por el arduino en cada iteración del arduino.

Copie el siguiente código en su Void Loop.

bucle vacío () {entrada (); // verifica la entrada de juego if (bolPlay == true) {if (intTick> = intDelay) {// verifica si el juego debe jugar un turno o continúa esperando Serial.println ("~~~~~~~ ~~ "); // imprimir para indicar que la placa se mueve en // writeSerial (); // si la opción está habilitada, escriba la placa en la serie buttonsGame (); // comprobar las entradas del jugador playBoard (); // mueve el tablero y agrega un nuevo mosaico clearLcd (); // limpia las pantallas LCD antes de dibujar drawBoard (); // dibuja el tablero en el bottomCheck () del lcd; intTick = 0; // restablecer intTick} else {buttonsGame (); // verifica las entradas del reproductor clearLcd (); // limpia las pantallas LCD antes de dibujar drawBoard (); // dibuja el tablero en la pantalla lcd intTick = intTick + intGameSpeed; // añadir a tick}} else {clearLcd (); // limpia las pantallas LCD antes de dibujar title (); // muestra los botones de información de título y puntuaciónMenu (); // leer la entrada del jugador clearBoard (); // asegurar que todo el tablero = 0} delay (10); // retrasa el arduino por un momento}

cuando bolPlay es igual a verdadero, significa que el juego se está reproduciendo, y todo el código para cuando se está jugando debe ejecutarse, pero solo queremos que el tablero agregue un nuevo mosaico y se mueva hacia abajo cuando intTick es mayor que nuestro intDelay, de lo contrario, queremos permitir que el usuario presione un botón para golpear un mosaico y que intTick aumente la velocidad.

La mayor parte de este código utiliza funciones que aún no hemos creado y las haremos en los siguientes pasos. El propósito de estas funciones es el siguiente.

La entrada lee qué botones ha pulsado el usuario.

botones El juego controla lo que hacen los botones cuando están en el juego y no en el menú.

playBoard agrega una nueva ficha al tablero y luego mueve todo el tablero hacia abajo un espacio

clearLCD limpia las pantallas LCD para asegurarse de que no queden fantasmas detrás de los mosaicos

drawBoard pasa por arrGame y lo imprime en las pantallas LCD

clearBoard borra todo arrGame cuando el juego no está en juego

bottomCheck comprueba la parte inferior de arrGame en busca de una condición de falla

título muestra el título del juego y la información de puntuación cuando está en el menú

El menú de botones controla lo que hacen las entradas del usuario cuando están en el menú.

gameOver es otra función, aunque no se llama aquí, sino en las funciones bottomCheck y buttonsGame.

Paso 5: la función ClearLCD

para crear una función comenzamos agregando esto al código

void functionName () {

}

el "functionName" puede ser cualquier cosa, siempre que no exista.

Copie este código en su programa:

void clearLcd () {for (int i = 0; i <= 15; i ++) {for (int ii = 0; ii <= 1; ii ++) {lcdLeft.setCursor (i, ii); lcdLeft.write (""); lcdRight.setCursor (i, ii); lcdRight.write (""); }}}

esto se ejecuta a través de toda la matriz mediante el uso de 2 bucles contados para pasar por cada punto en las pantallas LCD y escribir un espacio.

Sin restablecerse a nada, la pantalla LCD mantendrá lo que se escribió anteriormente

Paso 6: la función DrawBoard

copia este código en tu programa

void drawBoard () {for (int i = 1; i <= 15; i ++) {// dibuja las columnas 1 y 2 en la pantalla LCD izquierda // si el mosaico = 0 no escribe nada, = 1 escribe "#", = 2 escriba "@" lcdLeft.setCursor (i, 1); // establecer en la primera columna (más a la izquierda) if (arrGame [0] == 1) {lcdLeft.write ("#");} if (arrGame [0] == 2) {lcdLeft.escribir ("@");} lcdLeft.setCursor (i, 0); // establecer en la segunda columna (centro izquierda) if (arrGame [1] == 1) {lcdLeft.write ("#");} if (arrGame [1] == 2) {lcdLeft.escribir ("@");} lcdRight.setCursor (i, 1); // establecer en la tercera columna (centro derecha) if (arrGame [2] == 1) {lcdRight.write ("#");} if (arrGame [2] == 2) {lcdRight.escribir ("@");} lcdRight.setCursor (i, 0); // establecer en la cuarta columna (más a la derecha) if (arrGame [3] == 1) {lcdRight.write ("#");} if (arrGame [3] == 2) {lcdRight.escribir("@");} } }

Esto usa un bucle para recorrer cada fila del tablero, luego verifica si alguna columna en la fila es igual a 1 o 2, basándose en eso, luego imprime en la pantalla LCD un hashtag, para un mosaico que aún no se ha hit, o una @ para una ficha de hit.

Paso 7: la función PlayBoard

copie este código en su programa.

void playBoard () {for (int i = 0; i <= 3; i ++) {arrGame [0] = 0;} // borrar la fila superior arrGame [0] [random (0, 4)] = 1; // establece un punto aleatorio en la fila superior para que sea un mosaico para (int i = 15; i> = 1; i -) {// trabajando desde la parte inferior del tablero hacia la parte superior para (int ii = 0; ii <= 3; ii ++) {// para cada collum arrGame [ii] = arrGame [i - 1] [ii]; }}}

este código comienza limpiando toda la fila superior a 0, o ningún mosaico, y luego establece un mosaico aleatorio para que sea un 1, y un mosaico sin golpe.

Luego pasa por un ciclo contado en reversa, de 15 a 1, estableciendo la fila para que sea igual a la fila superior a la que es igual, haciendo que el tablero se mueva hacia abajo en la pantalla LCD.

Paso 8: la función ClearBoard

copie este código en su programa.

void clearBoard () {// restablecer los valores de tick y retardo intTick = 0; intDelay = 1000; // revisa el tablero y configura todo en 0 para (int i = 0; i <= 15; i ++) {for (int ii = 0; ii <= 3; ii ++) {arrGame [ii] = 0; }}}

Este código se ejecuta cuando el juego no se está reproduciendo para asegurarse de que todo arrGame esté configurado en 0, o sin mosaicos, mediante el uso de bucles contados para recorrer la matriz.

El código también restablece los valores de intDelay e intTick.

Paso 9: la función de título

copia el siguiente código en tu programa

void title () {// escribe el título en la pantalla LCD y el espacio para la puntuación lcdRight.setCursor (0, 0); lcdRight.write ("Azulejos de piano"); lcdRight.setCursor (0, 1); lcdRight.write ("Puntuación:"); // convierte la partitura en una cadena char strScore [3]; sprintf (strScore, "% d", intScore); // muestra la puntuación en la pantalla LCD lcdRight.write (strScore); // agrega la dificultad lcdRight.setCursor (10, 1); if (intDiff == 0) {lcdRight.write ("Fácil"); } if (intDiff == 1) {lcdRight.write ("Medio"); } if (intDiff == 2) {lcdRight.write ("Difícil"); } // Presione un poco de instrucción lcdLeft.setCursor (0, 0); lcdLeft.write ("Presione Enter"); lcdLeft.setCursor (0, 1); lcdLeft.write ("¡para empezar!"); }

Este código escribe el título del juego y la puntuación en las pantallas LCD, lo hace indicando a la pantalla LCD dónde empezar a escribir usando LCD.setCursor y luego escribiendo la cadena en LCD.write.

Aquí también se crea una nueva variable, strScore, que se usa para convertir intScore en un tipo de datos de cadena o char usando la función sprintf.

intDiff también se usa aquí, basado en sus valores imprime las diferentes opciones de dificultad.

Paso 10: Función ButtonsMenu

inserte el siguiente código en su programa

void buttonsMenu () {// cuando se presiona enter iniciar el juego y restablecer el valor de puntuación if (intEnter == 1) {bolPlay = true; intScore = 0; playBoard (); drawBoard (); } // cuando se presiona el botón 3, active la opción de depuración de imprimir la placa en serie if (intInput == 3) {if (bolSerialBoard == false) {Serial.println ("Placa serie activa"); bolSerialBoard = verdadero; } else {Serial.println ("Placa serie deshabilitada"); bolSerialBoard = falso; }} // establece la velocidad del juego en dificultad fácil if (intInput == 0) {Serial.print ("Juego configurado en fácil ("); Serial.print (intGameSpeedEasy); Serial.println ("aceleración ms)"); intDiff = 0; intGameSpeed = intGameSpeedEasy; } // establece la velocidad del juego en dificultad media if (intInput == 1) {Serial.print ("Juego establecido en medio ("); Serial.print (intGameSpeedMedium); Serial.println ("aceleración de ms)"); intDiff = 1; intGameSpeed = intGameSpeedMedium; } // establece la velocidad del juego en dificultad alta if (intInput == 2) {Serial.print ("Juego configurado en difícil ("); Serial.print (intGameSpeedHard); Serial.println ("aceleración ms)"); intDiff = 2; intGameSpeed = intGameSpeedHard; }}

este código solo se ejecuta cuando bolPlay es igual a falso en el bucle vacío

si intEnter se establece en 1, significa que se ha presionado el botón Enter; si se presiona, el programa establece bolPlay en verdadero y el juego comienza.

A continuación, el programa lee a qué es igual intInput. si es igual a 0 se presiona el primer botón de la izquierda, subiendo a la derecha hasta 3. Si intInput es igual a 4 no se presiona ningún botón.

si se presionan los botones 0-2, el juego cambia la dificultad, ajustando también el valor de velocidad del juego, lo que significa que se acelerará más rápido.

si se presiona el botón 3, el juego activará o desactivará un modo de depuración en el que se imprime todo el tablero en el monitor en serie para ayudar a encontrar problemas en el programa.

Paso 11: La función ButtonsGame

copia el siguiente código en tu programa

void buttonsGame () {if (intInput! = 4) {// si se presiona un botón if (bolTilePressed == false) {// solo si bolTilePressed es una acción de activación falsa para verificar una pulsación de botón bolTilePressed = true; // luego establezca bolTilePressed en true para asegurarse de que no se active de nuevo de forma accidental int intLowestTile = 0; // se establecerá en el mosaico con el mosaico más bajo int intCheckedTile = 15; // para realizar un seguimiento de los mosaicos que se han verificado mientras (intLowestTile == 0) {// siempre que no esté configurado para nada, verifique los mosaicos para (int i = 0; i 100) {// siempre que int el retraso no es inferior a 100 intDelay = intDelay - 20; // tomar un valor de él}} else {Serial.println ("Botón incorrecto presionado"); juego terminado(); // de lo contrario, el juego ha terminado}}}}}

El código solo se ejecuta cuando bolPlay es igual a verdadero en el bucle vacío.

Como botonesMenu basado en el valor de intInput, comprueba si el jugador ha golpeado una ficha o se ha perdido una.

Lo hace pasando por arrGame de abajo hacia arriba usando un bucle while para buscar qué fila es la más baja con un mosaico sin golpe. Luego verifica si el lugar en esa fila correspondiente al botón presionado es un mosaico sin presionar o no, si no lo está, lo establece en 2 en lugar de 1, lo que significa que se mostrará como una @, de lo contrario, activa el juegoOver función que aún tenemos que crear.

Esta función también utiliza la variable bolTilePressed estableciéndola en verdadero cuando se presiona un botón y en falso cuando no se presiona ningún botón. Esto es para asegurar que el usuario no pierda accidentalmente el juego porque el programa pensó que presionó el botón varias veces cuando lo mantuvo presionado.

Paso 12: la función GameOver

Copie el siguiente código en su programa

void gameOver () {Serial.println ("¡Juego terminado!"); Serial.print ("Tu puntuación fue:"); Serial.println (intScore); Serial.print ("Tu velocidad era:"); Serial.println (intDelay); bolPlay = falso; }

Esto se activa mediante las funciones checkBottom o buttonsGame y activa el final del juego estableciendo bolPlay en falso.

También imprime un mensaje en el monitor en serie para la puntuación de los usuarios y los mosaicos de velocidad se agregaron en milisegundos.

Paso 13: la función de entrada

Copie el siguiente código en su programa.

entrada vacía () {intEnter = digitalRead (btnEnter); // leer enter // leer cuál de las otras entradas, o si ninguna está establecida en 4 if (digitalRead (btn1) == HIGH) {intInput = 0;} else {if (digitalRead (btn2) == HIGH) {intInput = 1;} else {if (digitalRead (btn3) == HIGH) {intInput = 2;} else {if (digitalRead (btn4) == HIGH) {intInput = 3;} else {intInput = 4; }}}} // imprime en serie las entradas if (intEnter == 1) {Serial.println ("Enter Pressed!");} if (intInput! = 4) {Serial.print ("Button Press:"); Serial.println (intInput); } else {// si no se presiona ningún botón reset bolTilePressed bolTilePressed = false; }}

Este código se utiliza con las funciones buttonsGame y buttonsMenu. en función de los botones que el usuario ha presionado, establece el valor de intInput, o si no se presiona ningún botón, establece intInput en 4.

Si no se presiona ningún botón, aquí es donde bolTilePressed se restablece para la función buttonsGame.

También imprime un mensaje en el monitor de serie en el que se presiona el botón.

Paso 14: La función BottomCheck

copie el siguiente código en su programa.

void bottomCheck () {for (int i = 0; i <= 3; i ++) {// para las 4 columnas if (arrGame [15] == 1) {// si un mosaico está en la parte inferior Serial.println ("Mosaico en la parte inferior"); arrGame [15] = 2; drawBoard (); retraso (400); arrGame [15] = 1; drawBoard (); retraso (400); arrGame [15] = 2; drawBoard (); retraso (400); arrGame [15] = 1; drawBoard (); retraso (400); juego terminado(); }}}

usando un bucle, este código verifica la fila inferior de arrGame para ver si hay mosaicos sin golpe (mosaicos iguales a 1), si hay un mosaico sin golpe en la parte inferior de la pantalla, parpadeará el mosaico y luego activará la función de fin de juego.

Paso 15: La función WriteSerial

copia el siguiente código en tu programa

void writeSerial () {if (bolSerialBoard == true) {for (int i = 0; i <= 15; i ++) {for (int ii = 0; ii <= 3; ii ++) {Serial.print (arrGame [ii]); Serial.print (","); } Serial.println (""); }}}

Esta es la función seguida por la opción de depuración que se puede habilitar en la función de menú de botones. Si bolSerialBoard se establece en true en esa función, pasará por arrGame e imprimirá toda la placa en el monitor en serie con fines de prueba mediante el uso de una matriz.

Paso 16: ¡Finalización

¡Terminación!
¡Terminación!

¡Todo su código no debe estar completo y parecerse a esto!

/ * * Nombre - Piano Tiles; Arduino * Por - Domenic Marulli * Fecha - 11 / *

/ incluir bibliotecas

#incluir

// estas variables son opciones que puedes cambiar - números más altos = juego más rápido acelerado

int intGameSpeedEasy = 10; int intGameSpeedMedium = 25; int intGameSpeedHard = 80;

// Definir pines

#define btnEnter A0 #define btn1 15 #define btn2 16 #define btn3 17 #define btn4 18

// crea objetos LCD (n, ~, n, ~, ~, n)

LiquidCrystal lcdLeft (8, 9, 12, 10, 11, 13); LiquidCrystal lcdRight (2, 3, 4, 5, 6, 7);

// configurar la matriz del juego

int arrGame [16] [4] = {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}};

// configurar variables para el juego

boolean bolPlay; // rastrea si el jugador int intScore; // rastrea la puntuación del jugador int intDiff; // solo una cosa estética para decir en qué dificultad se encuentra el juego

// configurar variables para entrada

int intEnter; // rastrea si el usuario presiona el botón enter int intInput; // rastrea qué botones presiona el usuario boolean bolTilePressed; // asegúrese de que el jugador no presione accidentalmente un botón 5 veces y pierda

// configurar variables para el turno

int intTick; // cuenta milies (por ciclo) hasta intDelay int intDelay; // el tiempo que el programa espera hasta el próximo turno en milis int intGameSpeed;

// un poco de opciones de depuración

boolean bolSerialBoard; // cuando sea verdadero imprimirá la placa en el monitor serial

// la configuración que se ejecutará una vez

configuración vacía () {Serial.begin (9600); // iniciar el monitor serial // configurar las variables bolPlay = false; intScore = 0; intTick = 0; intDelay = 1000; intDiff = 1; intGameSpeed = intGameSpeedMedium; // comienza lcdLeft.begin de lcd (16, 2); lcdRight.begin (16, 2); }

// el bucle que se ejecutará cada 10 milisegundos

bucle vacío () {entrada (); // verifica la entrada de juego if (bolPlay == true) {if (intTick> = intDelay) {// verifica si el juego debe jugar un turno o continúa esperando Serial.println ("~~~~~~~ ~~ "); // imprimir para indicar que la placa se mueve en // writeSerial (); // si la opción está habilitada, escriba la placa en la serie buttonsGame (); // comprobar las entradas del jugador playBoard (); // mueve el tablero y agrega un nuevo mosaico clearLcd (); // limpia las pantallas LCD antes de dibujar drawBoard (); // dibuja el tablero en el bottomCheck () del lcd; intTick = 0; // restablecer intTick} else {buttonsGame (); // verifica las entradas del reproductor clearLcd (); // limpia las pantallas LCD antes de dibujar drawBoard (); // dibuja el tablero en la pantalla lcd intTick = intTick + intGameSpeed; // añadir a tick}} else {clearLcd (); // limpia las pantallas LCD antes de dibujar title (); // muestra los botones de información de título y puntuaciónMenu (); // leer la entrada del jugador clearBoard (); // asegurar que todo el tablero = 0} delay (10); // retrasa el arduino por un momento}

// limpia la pantalla LCD, por lo que las celdas no ingresadas no se dejan allí

void clearLcd () {for (int i = 0; i <= 15; i ++) {for (int ii = 0; ii <= 1; ii ++) {lcdLeft.setCursor (i, ii); lcdLeft.write (""); lcdRight.setCursor (i, ii); lcdRight.write (""); }}}

// dibuja el tablero en el lcd

void drawBoard () {for (int i = 1; i <= 15; i ++) {// dibuja las columnas 1 y 2 en la pantalla LCD izquierda // si el mosaico = 0 no escribe nada, = 1 escribe "#", = 2 escriba "@" lcdLeft.setCursor (i, 1); // establecer en la primera columna (más a la izquierda) if (arrGame [0] == 1) {lcdLeft.write ("#");} if (arrGame [0] == 2) {lcdLeft.escribir ("@");} lcdLeft.setCursor (i, 0); // establecer en la segunda columna (centro izquierda) if (arrGame [1] == 1) {lcdLeft.write ("#");} if (arrGame [1] == 2) {lcdLeft.escribir ("@");} lcdRight.setCursor (i, 1); // establecer en la tercera columna (centro derecha) if (arrGame [2] == 1) {lcdRight.write ("#");} if (arrGame [2] == 2) {lcdRight.escribir ("@");} lcdRight.setCursor (i, 0); // establecer en la cuarta columna (más a la derecha) if (arrGame [3] == 1) {lcdRight.write ("#");} if (arrGame [3] == 2) {lcdRight.escribir("@");} } }

// mueve el tablero hacia abajo y coloca un valor aleatorio para ser una ficha

void playBoard () {for (int i = 0; i <= 3; i ++) {arrGame [0] = 0;} // borrar la fila superior arrGame [0] [random (0, 4)] = 1; // establece un punto aleatorio en la fila superior para que sea un mosaico para (int i = 15; i> = 1; i -) {// trabajando desde la parte inferior del tablero hacia la parte superior para (int ii = 0; ii <= 3; ii ++) {// para cada collum arrGame [ii] = arrGame [i - 1] [ii]; }}}

// establece todo el tablero en 0 y restablece las variables a antes del juego

void clearBoard () {// restablecer los valores de tick y retardo intTick = 0; intDelay = 1000; // revisa el tablero y configura todo en 0 para (int i = 0; i <= 15; i ++) {for (int ii = 0; ii <= 3; ii ++) {arrGame [ii] = 0; }}}

// muestra el menú principal en la pantalla LCD

void title () {// escribe el título en la pantalla LCD y el espacio para la puntuación lcdRight.setCursor (0, 0); lcdRight.write ("Azulejos de piano"); lcdRight.setCursor (0, 1); lcdRight.write ("Puntuación:"); // convierte la partitura en una cadena char strScore [3]; sprintf (strScore, "% d", intScore); // muestra la puntuación en la pantalla LCD lcdRight.write (strScore); // agrega la dificultad lcdRight.setCursor (10, 1); if (intDiff == 0) {lcdRight.write ("Fácil"); } if (intDiff == 1) {lcdRight.write ("Medio"); } if (intDiff == 2) {lcdRight.write ("Difícil"); } // Presione un poco de instrucción lcdLeft.setCursor (0, 0); lcdLeft.write ("Presione Enter"); lcdLeft.setCursor (0, 1); lcdLeft.write ("¡para empezar!"); }

// comprueba los botones y qué hacer con ellos mientras está fuera del juego

void buttonsMenu () {// cuando se presiona enter iniciar el juego y restablecer el valor de puntuación if (intEnter == 1) {bolPlay = true; intScore = 0; playBoard (); drawBoard (); } // cuando se presiona el botón 3, active la opción de depuración de imprimir la placa en serie if (intInput == 3) {if (bolSerialBoard == false) {Serial.println ("Placa serie activa"); bolSerialBoard = verdadero; } else {Serial.println ("Placa serie deshabilitada"); bolSerialBoard = falso; }} // establece la velocidad del juego en dificultad fácil if (intInput == 0) {Serial.print ("Juego configurado en fácil ("); Serial.print (intGameSpeedEasy); Serial.println ("aceleración ms)"); intDiff = 0; intGameSpeed = intGameSpeedEasy; } // establece la velocidad del juego en dificultad media if (intInput == 1) {Serial.print ("Juego establecido en medio ("); Serial.print (intGameSpeedMedium); Serial.println ("aceleración de ms)"); intDiff = 1; intGameSpeed = intGameSpeedMedium; } // establece la velocidad del juego en dificultad alta if (intInput == 2) {Serial.print ("Juego configurado en difícil ("); Serial.print (intGameSpeedHard); Serial.println ("aceleración ms)"); intDiff = 2; intGameSpeed = intGameSpeedHard; }}

// comprueba los botones y qué hacer con ellos durante el juego

void buttonsGame () {if (intInput! = 4) {// si se presiona un botón if (bolTilePressed == false) {// solo si bolTilePressed es una acción de activación falsa para verificar una pulsación de botón bolTilePressed = true; // luego establezca bolTilePressed en true para asegurarse de que no se active de nuevo de forma accidental int intLowestTile = 0; // se establecerá en el mosaico con el mosaico más bajo int intCheckedTile = 15; // para realizar un seguimiento de los mosaicos que se han verificado mientras (intLowestTile == 0) {// siempre que no esté configurado para nada, verifique los mosaicos para (int i = 0; i 100) {// siempre que int el retraso no es inferior a 100 intDelay = intDelay - 20; // tomar un valor de él}} else {Serial.println ("Botón incorrecto presionado"); juego terminado(); // de lo contrario, el juego ha terminado}}}}}

void gameOver () {

Serial.println ("¡Juego terminado!"); Serial.print ("Tu puntuación fue:"); Serial.println (intScore); Serial.print ("Tu velocidad era:"); Serial.println (intDelay); bolPlay = falso; }

// comprueba la entrada del jugador

entrada vacía () {intEnter = digitalRead (btnEnter); // leer enter // leer cuál de las otras entradas, o si ninguna está establecida en 4 if (digitalRead (btn1) == HIGH) {intInput = 0;} else {if (digitalRead (btn2) == HIGH) {intInput = 1;} else {if (digitalRead (btn3) == HIGH) {intInput = 2;} else {if (digitalRead (btn4) == HIGH) {intInput = 3;} else {intInput = 4; }}}} // imprime en serie las entradas if (intEnter == 1) {Serial.println ("Enter Pressed!");} if (intInput! = 4) {Serial.print ("Button Press:"); Serial.println (intInput); } else {// si no se presiona ningún botón reset bolTilePressed bolTilePressed = false; }}

// comprueba la parte inferior del tablero en busca de fallas

void bottomCheck () {for (int i = 0; i <= 3; i ++) {// para las 4 columnas if (arrGame [15] == 1) {// si un mosaico está en la parte inferior Serial.println ("Mosaico en la parte inferior"); arrGame [15] = 2; drawBoard (); retraso (400); arrGame [15] = 1; drawBoard (); retraso (400); arrGame [15] = 2; drawBoard (); retraso (400); arrGame [15] = 1; drawBoard (); retraso (400); juego terminado(); }}}

// imprime la placa en el monitor serial si bolSerialBoard es verdadero

void writeSerial () {if (bolSerialBoard == true) {for (int i = 0; i <= 15; i ++) {for (int ii = 0; ii <= 3; ii ++) {Serial.print (arrGame [ii]); Serial.print (","); } Serial.println (""); }}}

Una vez que ingrese todo el código, cárguelo en su arduino y ¡disfrute!

Recomendado: