Ping Pong con LCD 16×2

Me acordé de cuando vendía los primeros videojuegos en el negocio familiar que iban conectados a las TV.

Se me ocurrió hacer aquel primer videojuego en arduino. En realidad primero busque por internet si encontraba algo que se ajustase a lo que tenia en mente. Lo vi y me pareció muy acertado con lo cual lo monté en mi protoboard para ver como funcionaba.

Al comprobar su funcionamiento, lo que hice fue incorporar una tira de leds RGB que con un solo pin podemos controlar toda la tira. Lo que he hecho que los primeros 4 leds fueran para el jugador de la izquierda y los 4 restantes son para el jugador de la derecha. De esta forma cuando el jugador que gana suena el zumbador y al mismo tiempo se ilumina la tira de leds; para el ganador de color verde y el perdedor de color rojo.

Me acordé de cuando vendía los primeros videojuegos en el negocio familiar que iban conectados a las TV.

Se me ocurrió hacer aquel primer videojuego en arduino. En realidad primero busque por internet si encontraba algo que se ajustase a lo que tenia en mente. Lo vi y me pareció muy acertado con lo cual lo monté en mi protoboard para ver como funcionaba.

Al comprobar su funcionamiento, lo que hice fue incorporar una tira de leds RGB que con un solo pin podemos controlar toda la tira. Lo que he hecho que los primeros 4 leds fueran para el jugador de la izquierda y los 4 restantes son para el jugador de la derecha. De esta forma cuando el jugador que gana suena el zumbador y al mismo tiempo se ilumina la tira de leds; para el ganador de color verde y el perdedor de color rojo.

La librería que utiliza estos leds es la llamada “Adafruit” que os la dejo aquí.

Materiales:

1 Arduino UNO
1 LCD I2C
6 Botones
6 Resisténcias 10K
1 tira de LEDS RGB
1 Buzzer

Esquema de conexión:

Código fuente:

// Incluye la libreria LiquidCrystal_I2C
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// configuración LCD a 0x27 para una visualización de 16x2
LiquidCrystal_I2C lcd(0x27, 16, 2);

// Incluye la libreria Adafruit_NeoPixel
#include <Adafruit_NeoPixel.h>

#define neoPixel2 12   //1
#define LEDs 8

// Crea la variable NeoPixel strip2
Adafruit_NeoPixel strip2 = Adafruit_NeoPixel(LEDs, neoPixel2, NEO_GRB + NEO_KHZ800);

//Pulsador de inicio o Start
#define start 8
// Jugador 1 pulsador hacia arriba
#define P1U 6
// Jugador 1 pulsador hacia abajo
#define P1D 7
// Jugador 2 pulsador hacia arriba
#define P2U 10
// Jugador 1 pulsador hacia abajo
#define P2D 9
// Zumbador
#define piezo 11
int jugador1 = 0;
int jugador2 = 0;

//Pala 1
byte paddle1[16] = {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0};  // matriz para contenir los valores de la fila LCD-0 y 1 de la pala
byte player11[8] = {0, 0, 0, 0, 0, 0, 1, 1};              // matriz para mantener los valores de la fila 0 de la pantalla LCD de la pala 1
byte player12[8] = {1, 1, 0, 0, 0, 0, 0, 0};              // matriz para mantener los valores de la fila 1 de la pantalla LCD de la pala 1

//Pala 2
byte paddle2[16] = {0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0}; // matriz para contenir los valores de la fila LCD-0 y 2 de la pala
byte player21[8] = {0, 0, 0, 0, 0, 0, 16, 16};              // matriz para mantener los valores de la fila 0 de la pantalla LCD de la pala 2
byte player22[8] = {16, 16, 0, 0, 0, 0, 0, 0};              // matriz para mantener los valores de la fila 1 de la pantalla LCD de la pala 2

//Pelota
byte ball[16] = {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0};   // matriz para contener los valores de fila 0 y 1 de la bola LCD
byte ball1[8] = {0, 0, 0, 0, 0, 0, 0, 1};               // matriz para mantener los valores de fila 0 de la bola LCD
byte ball2[8] = {0, 0, 0, 0, 0, 0, 0, 0};               // matriz para mantener los valores de fila 1 de la bola LCD

/*
  x                    - cursor para pelota
     rebote      - estado del rebote (0 - la bola se mueve hacia abajo, 1 - la bola se mueve hacia arriba)
     direction   - direction of ball (L - izquierda, R - derecha)
     v1, v2 y v3:  variables utilizadas para verificar si la pelota golpea las paletas o no
     puntaje1    - puntaje del jugador1
     score2      - puntaje del jugador2
     juego       - inicio / detención (0 - detención, 1 - inicio)
*/
int x = 0, bounce = 0, v1 = 0, v2 = 0, v3 = 0;
char direction = 'L';
int score1 = 0, score2 = 0;
boolean game = 0;
int a = 0;

/*----------------------------------------función setup--------------------------------*/
void setup() {

  // inicializamos li tira de leds Neo_pixel
  strip2.begin();
  strip2.show();

  pinMode(P1U, INPUT);         // inicializamos los pulsadores como entradas
  pinMode(P1D, INPUT);
  pinMode(P2U, INPUT);
  pinMode(P2D, INPUT);
  pinMode(start, INPUT);
  pinMode(piezo, OUTPUT);      // inicializamos el zumbador

  lcd.init();                  // inicializamos la LCD
  lcd.backlight();

  piezoSound(50);              // el zumbador sonara durante 50 ms
  lcd.clear();                 // borramos la LCD
  lcd.setCursor(2, 0);         // set LCD cursor to (2, 0)
  lcd.print("Arduino UNO");   // print data on LCD display
  lcd.setCursor(1, 1);
  lcd.print("-- Ping Pong --");
  delay(1500);

  lcd.clear();
  lcd.setCursor(6, 0);
  lcd.print("Autor");
  lcd.setCursor(1, 1);
  lcd.print("JOSEP MARTINEZ");
  delay(3000);
}
/*----------------------------------------termina la función setup--------------------------------*/

/*----------------------------------------------Función loop--------------------------------------*/
void loop() {

  //ejecutó este ciclo mientras se presiona el pulsador de inicio
  while (game == 0) {
    for (a; a < 1; a++) {
      for (int i = 0; i < 16; i++) {
        if (6 <= i && i <= 9) {
          paddle1[i] = 1;
          paddle2[i] = 16;
        }

        else {
          paddle1[i] = 0;
          paddle2[i] = 0;
        }

        if (i == 7)ball[i] = 1;
        else ball[i] = 0;
      }
      x = 8;              // poner el cursor de bola en 8
      lcd.clear();
      lcd.setCursor(1, 0);
      lcd.print("Prsiona iniciar");
      lcd.setCursor(2, 1);
      lcd.print("boto central");
    }

    // compruebe si se presiona el botón de inicio
    if (digitalRead(start) == HIGH) {
      lcd.clear();
      lcd.setCursor(5, 0);
      lcd.print("Jugador");
      lcd.setCursor(0, 1);
      lcd.print("1");
      lcd.setCursor(15, 1);
      lcd.print("2");
      delay(2000);

      for (int i = 3; i > 0; i--) {
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Estas preparat!");
        lcd.setCursor(8, 1);
        lcd.print(i);
        if (i == 1)piezoSound(100);
        delay(1000);
      }
      a = 0;
      game = 1;             // establece el juego a 1, sale del bucle while e inicia el juego
    }
    delay(100);
  }

  // comienza el juego
  // cuando se presiona P1U, la pala1 se mueve hacia arriba
  if (digitalRead(P1U) == HIGH) {
    paddle1Up();
    delay(50);
  }

  // cuando se presiona P1D, la pala1 se mueve hacia abajo
  if (digitalRead(P1D) == HIGH) {
    paddle1Down();
    delay(50);
  }

  // cuando se presiona P1U, la paleta1 se mueve hacia arriba
  if (digitalRead(P2U) == HIGH) {
    paddle2Up();
    delay(50);
  }

  // cuando se presiona P2D, la pala2 se mueve hacia abajo
  if (digitalRead(P2D) == HIGH) {
    paddle2Down();
    delay(50);
  }

  // divide la matriz paddle1 en 2 matrices, paddle11 y paddle12
  for (int i = 0; i <= 7; i++) {
    player11[i] = paddle1[i];
  }

  for (int i = 0, j = 8; i <= 7, j <= 15; i++, j++) {
    player12[i] = paddle1[j];
  }

  // divide la matriz paddle2 en 2 matrices, paddle21 y paddle22
  for (int i = 0; i <= 7; i++) {
    player21[i] = paddle2[i];
  }

  for (int i = 0, j = 8; i <= 7, j <= 15; i++, j++) {
    player22[i] = paddle2[j];
  }

  //dividir la matriz de bolas en 2 matrices, ball11 y ball12
  for (int i = 0; i <= 7; i++) {
    ball1[i] = ball[i];
  }

  for (int i = 0, j = 8; i <= 7, j <= 15; i++, j++) {
    ball2[i] = ball[j];
  }

  //crear formas personalizadas para pala 1, pala 2 y la balo
  lcd.createChar(0, player11);
  lcd.createChar(1, player12);
  lcd.createChar(2, player21);
  lcd.createChar(3, player22);
  lcd.createChar(4, ball1);
  lcd.createChar(5, ball2);

  //imprime la pala 1, pala 2 y la bola
  lcd.clear();
  lcd.setCursor(0, 0);  // posición de puntaje 1
  lcd.print(score1);
  lcd.setCursor(0, 1);  // posición de puntaje 2
  lcd.print(score2);
    //Puntuación
  lcd.setCursor(2,0);
  lcd.print(jugador1);
  lcd.setCursor(2,1);
  lcd.print(jugador2);

  lcd.setCursor(3, 0);  // posición del jugador11
  lcd.write(byte(0));
  lcd.setCursor(3, 1);  // posición del jugador12
  lcd.write(byte(1));
  lcd.setCursor(15, 0); // posición del jugador21
  lcd.write(byte(2));
  lcd.setCursor(15, 1); // posición del jugador22
  lcd.write(byte(3));
  lcd.setCursor(x, 0);  // La posición de la bola1, x se cambia para mover la bola en la pantalla
  lcd.write(byte(4));
  lcd.setCursor(x, 1);  // La posición de la bola2, x se cambia para mover la bola en la pantalla
  lcd.write(byte(5));

  // comprueba si la pelota golpea la paleta1
  if (x == 3) {
    for (int b = 0; b < 16; b++) {
      if (ball[b] != 0) {
        v1 = ball[b];
        v2 = paddle1[b];
      }
    }

    // si la pelota colpea la pala 1, canvia la dirección de la bola a R (drecha)
    if (v1 == v2) {
      direction = 'R';
      score1 += 1;
      piezoSound(10);
    }

    // si no, muestra el ganador
    else {
      lcd.clear();
      lcd.setCursor(3, 0);
      lcd.print("Fin del juego");
      lcd.setCursor(1, 1);
      lcd.print("Ha ganado el 2");
      jugador2 = jugador2 + 1;

      // cuatro LEDs verde brillante para el ganador y 4 LEDs rojo para el perdedor, con un sonido de cristal eléctrico piezo
      for (int i = 0; i < 3; i++) {  // Repite 3 veces
       for (int j=0; j < 4; j++) {
        strip2.setPixelColor(j, strip2.Color(15, 0, 0));
        strip2.show();
          for (int j=4; j < 8; j++) {
          strip2.setPixelColor(j, strip2.Color(0, 15, 0));
          strip2.show();
       }
      }

        piezoSound(500);
        delay(500);
        for (int j=0; j < 8; j++) {
         strip2.setPixelColor(j, strip2.Color(0, 0, 0));
         strip2.show();
        }
        delay(500);

   }

      // establece los puntos a 0 y reinicia el juego
      score1 = score2 = 0;
      delay(1000);
      game = 0;
    }
  }

  // comprueba si el pelota golpea en la paleta2
  if (x == 15) {
    for (int b = 0; b < 16; b++) {
      if (ball[b] != 0) {
        v1 = ball[b];
        v3 = paddle2[b];
      }
    }

    // si el pelota golpea paddle2, cambia la dirección de la bola a L (izquierda)
    if (v1 == v3) {
      direction = 'L';
      score2 += 1;
      piezoSound(10);
    }

    // si no, muestrau el ganador
    else {
      lcd.clear();
      lcd.setCursor(3, 0);
      lcd.print("Fin del juego");
      lcd.setCursor(1, 1);
      lcd.print("Ha ganado el 1");
      jugador1 = jugador1 + 1;

      // cuatro LEDs verde brillante para el ganador y 4 LEDs rojo para el perdedor, con un sonido de cristal eléctrico piezo
      for (int i = 0; i < 3; i++) {  // Repite 3 veces

       for (int j=0; j < 4; j++) {
        strip2.setPixelColor(j, strip2.Color(0, 15, 0));
        strip2.show();
          for (int j=4; j < 8; j++) {
          strip2.setPixelColor(j, strip2.Color(15, 0, 0));
          strip2.show();
       }
      }
        piezoSound(500);
        delay(500);
        for (int j=0; j < 8; j++) {
          strip2.setPixelColor(j, strip2.Color(0, 0, 0));
        }
        strip2.show();
        delay(500);
      }

      // establece los puntos a 0 y reinicia el juego
      score1 = score2 = 0;
      delay(1000);
      game = 0;
    }
  }

  // si la dirección es L (izquierda), desplaza el balón a la izquierda
  if (direction == 'L') {
    for (int b = 0; b < 16; b++)
      if (ball[b] == 16) x -= 1;

    if (bounce == 0)
      ballLeftDown();
    else
      ballLeftUp();
  }

  // si la dirección es R (derecha), desplaza el balón a la derecha
  if (direction == 'R') {
    for (int b = 0; b < 16; b++)
      if (ball[b] == 1) x += 1;

    if (bounce == 0)
      ballRightDown();
    else
      ballRightUp();
  }
}

/*----------------------------------------Fin de la función loop-------------------------------*/

/*-------------------------------------------otras funciones-----------------------------------*/

//paddle1Up función
void paddle1Up() {
  if (paddle1[0] != 1) {
    int temp = paddle1[0], i;
    for (i = 0; i < 15; i++)
      paddle1[i] = paddle1[i + 1];
    paddle1[i] = temp;
  }
}

//paddle1Down función
void paddle1Down() {
  if (paddle1[15] != 1) {
    int temp = paddle1[15], i;
    for (i = 15; i > 0; i--)
      paddle1[i] = paddle1[i - 1];
    paddle1[i] = temp;
  }
}

//paddle2Up función
void paddle2Up() {
  if (paddle2[0] != 16) {
    int temp = paddle2[0], i;
    for (i = 0; i < 15; i++)
      paddle2[i] = paddle2[i + 1];
    paddle2[i] = temp;
  }
}

//paddle2Down función
void paddle2Down() {
  if (paddle2[15] != 16) {
    int temp = paddle2[15], i;
    for (i = 15; i > 0; i--)
      paddle2[i] = paddle2[i - 1];
    paddle2[i] = temp;
  }
}

//ballLeftDown función
void ballLeftDown() {

  if (ball[15] == 0) {
    int temp = ball[15], i;
    for (i = 15; i > 0; i--)
      ball[i] = ball[i - 1];
    ball[i] = temp;
    ballLeft();
  }
  else {
    bounce = 1;
    piezoSound(10);
  }
}

//ballLeftUp función
void ballLeftUp() {

  if (ball[0] == 0) {
    int temp = ball[0], i;
    for (i = 0; i < 15; i++)
      ball[i] = ball[i + 1];
    ball[i] = temp;
    ballLeft();
  }
  else {
    bounce = 0;
    piezoSound(10);
  }
}

//ballRightDown función
void ballRightDown() {

  if (ball[15] == 0) {
    int temp = ball[15], i;
    for (i = 15; i > 0; i--)
      ball[i] = ball[i - 1];
    ball[i] = temp;
    ballRight();
  }
  else {
    bounce = 1;
    piezoSound(10);
  }
}

//ballRightUp función
void ballRightUp() {

  if (ball[0] == 0) {
    int temp = ball[0], i;
    for (i = 0; i < 15; i++)
      ball[i] = ball[i + 1];
    ball[i] = temp;
    ballRight();
  }
  else {
    bounce = 0;
    piezoSound(10);
  }
}

// ballRight función
void ballRight() {
  for (int b = 0; b < 16; b++) {
    if (ball[b] != 0) {
      if (ball[b] == 16)ball[b] = 8;
      else if (ball[b] == 8) ball[b] = 4;
      else if (ball[b] == 4) ball[b] = 2;
      else if (ball[b] == 2) ball[b] = 1;
      else if (ball[b] == 1) ball[b] = 16;
    }
  }
}

// ballLeft función
void ballLeft() {
  for (int b = 0; b < 16; b++) {
    if (ball[b] != 0) {
      if (ball[b] == 1)ball[b] = 2;
      else if (ball[b] == 2) ball[b] = 4;
      else if (ball[b] == 4) ball[b] = 8;
      else if (ball[b] == 8)ball[b] = 16;
      else if (ball[b] == 16)ball[b] = 1;
    }
  }
}

//piezoSound función
void piezoSound(int d) {
  analogWrite(piezo, 20);
  delay(d);
  analogWrite(piezo, 0);
}

/*----------------------------------------Fin de las demas funciones----------------------------*/

/*-----------------------------------------------Fin del programa-------------------------------*/
Scroll al inicio