Estoy contento de anunciar que al fin he terminado el videojuego que comencé hace casi un mes. Se trata del juego de la serpiente, viborita, snake o como lo conozcas; pero en Arduino usando una LCD.
Vamos a usar cosas simples, pero si eres un principiante te recomiendo leer los enlaces que dejo a continuación. Para empezar, vamos a generar números aleatorios con Arduino; esto servirá para colocar la comida de manera aleatoria.
Hay que notar que no he conectado el botón del joystick, pues por ahora no tiene ningún uso.
Como lo dije, una de las mejoras o actualizaciones es que se coloca comida de manera aleatoria en el escenario.
Para dibujar la comida tenemos dos funciones; una de ella calcula las coordenadas y la otra la coloca sobre el escenario:
Le damos seguimiento a la posición de la comida y calculamos si la serpiente colisiona con la misma, es decir, sabemos si la serpiente come, valga la redundancia, comida (podemos imaginar que la serpiente es una anaconda y la comida es un ratón).
De igual modo ahora el puntaje se aumenta de manera correcta.
También tenemos una función que lee un joystick y devuelve la dirección hacia la que se debe dirigir la serpiente:
Finalmente dejaré la prueba de que todo funciona. Primero, el código:
#include <LiquidCrystal_I2C.h>
#define ANCHURA_LCD 16
#define ALTURA_LCD 2
#define DIRECCION_LCD 0x3F
#define ALTURA_TABLERO 16
#define ANCHURA_TABLERO 20
#define MAXIMA_LONGITUD_SERPIENTE (ALTURA_TABLERO * ANCHURA_TABLERO)
#define DIRECCION_DERECHA 0
#define DIRECCION_IZQUIERDA 1
#define DIRECCION_ARRIBA 2
#define DIRECCION_ABAJO 3
const int pinX = 0,
pinY = 1;
LiquidCrystal_I2C pantalla(DIRECCION_LCD, ANCHURA_LCD, ALTURA_LCD);
int escenario[ALTURA_TABLERO][ANCHURA_TABLERO] = {
{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, 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, 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, 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, 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,},
};
class PedazoSerpiente {
public:
int x, y;
PedazoSerpiente(int a, int b) {
x = a; y = b;
}
PedazoSerpiente() {
}
};
PedazoSerpiente serpiente[MAXIMA_LONGITUD_SERPIENTE];
int longitudSerpiente = 0;
int direccion = DIRECCION_DERECHA;
int comidaX, comidaY;
int puntaje = 0;
int obtenerDireccion() {
int valorX = analogRead(pinX),
valorY = analogRead(pinY);
if (valorX > 1000) {
return DIRECCION_ARRIBA;
} else if (valorX < 200) {
return DIRECCION_ABAJO;
}
if (valorY > 1000) {
return DIRECCION_DERECHA;
} else if (valorY < 200) {
return DIRECCION_IZQUIERDA;
}
return -1;
}
void cambiarDireccion(int nuevaDireccion) {
if (
nuevaDireccion != DIRECCION_DERECHA
&& nuevaDireccion != DIRECCION_IZQUIERDA
&& nuevaDireccion != DIRECCION_ARRIBA
&& nuevaDireccion != DIRECCION_ABAJO
) {
return;
}
if (
(nuevaDireccion == DIRECCION_DERECHA || nuevaDireccion == DIRECCION_IZQUIERDA)
&& (direccion == DIRECCION_DERECHA || direccion == DIRECCION_IZQUIERDA)
) return;
if (
(nuevaDireccion == DIRECCION_ARRIBA || nuevaDireccion == DIRECCION_ABAJO)
&& (direccion == DIRECCION_ARRIBA || direccion == DIRECCION_ABAJO)
) return;
direccion = nuevaDireccion;
}
void agregarPedazo(int x, int y) {
if (longitudSerpiente >= MAXIMA_LONGITUD_SERPIENTE) return;
if (x + 1 >= ANCHURA_TABLERO || x < 0)return;
if (y + 1 >= ALTURA_TABLERO || y < 0)return;
serpiente[longitudSerpiente] = PedazoSerpiente(x, y);
longitudSerpiente++;
}
void moverSerpiente() {
for (int i = longitudSerpiente - 1; i >= 1; i--) {
serpiente[i].x = serpiente[i - 1].x;
serpiente[i].y = serpiente[i - 1].y;
}
switch (direccion) {
case DIRECCION_DERECHA:
if (serpiente[0].x + 1 >= ANCHURA_TABLERO)serpiente[0].x = 0;
else serpiente[0].x++;
break;
case DIRECCION_IZQUIERDA:
if (serpiente[0].x <= 0)serpiente[0].x = ANCHURA_TABLERO - 1;
else serpiente[0].x--;
break;
case DIRECCION_ARRIBA:
if (serpiente[0].y <= 0)serpiente[0].y = ALTURA_TABLERO - 1;
else serpiente[0].y--;
break;
case DIRECCION_ABAJO:
if (serpiente[0].y + 1 >= ALTURA_TABLERO)serpiente[0].y = 0;
else serpiente[0].y++;
break;
}
}
void colocarSerpienteEnMatriz() {
for (int i = 0; i < longitudSerpiente; i++) {
int x = serpiente[i].y,
y = serpiente[i].x;
escenario[x][y] = 1;
}
}
void randomizarComida() {
comidaX = random(0, ANCHURA_TABLERO);
comidaY = random(0, ALTURA_TABLERO);
}
void acomodarComida() {
escenario[comidaY][comidaX] = 1;
}
void setup() {
randomSeed(analogRead(0));
pantalla.init();
pantalla.backlight();
for (int i = 0; i < 3; i++) {
agregarPedazo(5, i);
}
randomizarComida();
pantalla.setCursor(0, 0);
pantalla.print("Snake");
pantalla.setCursor(0, 1);
pantalla.print("By Parzibyte");
delay(700);
pantalla.clear();
}
void dibujarPuntaje() {
pantalla.setCursor(6, 0);
pantalla.print("SCORE");
pantalla.setCursor(6, 1);
pantalla.print(puntaje);
}
void dibujarMatriz() {
byte figura[8];
int numeroFigura = 0;
for (int cuadritoX = 0; cuadritoX < 4; cuadritoX++) {
for (int cuadritoY = 0; cuadritoY < 2; cuadritoY++) {
for (int x = 0; x < 8; x++) {
int numero = 0;
int indice = cuadritoY == 0 ? x : (x + 8);
int inicio = cuadritoX * 5;
if (escenario[indice][inicio + 0] == 1)
numero += 16;
if (escenario[indice][inicio + 1] == 1)
numero += 8;
if (escenario[indice][inicio + 2] == 1)
numero += 4;
if (escenario[indice][inicio + 3] == 1)
numero += 2;
if (escenario[indice][inicio + 4] == 1)
numero += 1;
figura[x] = numero;
}
pantalla.createChar(numeroFigura, figura);
pantalla.setCursor(cuadritoX, cuadritoY);
pantalla.write(byte(numeroFigura));
numeroFigura++;
}
}
}
void limpiarMatriz() {
for (int y = 0; y < 16; y++) {
for (int x = 0; x < 20; x++) {
escenario[y][x] = 0;
}
}
}
bool colisionaConComida() {
return serpiente[0].x == comidaX && serpiente[0].y == comidaY;
}
void loop() {
limpiarMatriz();
cambiarDireccion(obtenerDireccion());
moverSerpiente();
colocarSerpienteEnMatriz();
acomodarComida();
dibujarMatriz();
if (colisionaConComida()) {
puntaje++;
randomizarComida();
agregarPedazo(0, 0);
}
dibujarPuntaje();
delay(10);
}
De hecho nadie solicitó este juego y no fue un requisito de ningún modo, simplemente fue un capricho. Lo intenté hacer hace algún largo tiempo y no pude, pero al intentarlo de nuevo, lo logré y quedó estupendo.
Buenas tardes, queria consultar que libreria estan utilizando ya que liquidCrystal.h de arduino no me toma el programa
Creo que es LiquidCrystal_I2C
hay un error, no sé a que se refiera, ya pude la dirección LCD, y las librerías y me dice esto:
es un texto más grande pero se va repitiendo esto varias veces
In file included from C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.49.0_x86__mdqgnx93n4wtt\hardware\arduino\avr\cores\arduino/Arduino.h:32:0,
from sketch\Proyecto.ino.cpp:1:
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.49.0_x86__mdqgnx93n4wtt\hardware\arduino\avr\cores\arduino/binary.h:58:0: note: this is the location of the previous definition
#define B00000100 4
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.49.0_x86__mdqgnx93n4wtt\hardware\arduino\avr\cores\arduino/binary.h:58:19: error: expected ‘,’ or ‘…’ before numeric constant
#define B00000100 4
^
C:\Users\Pedro\OneDrive\Documentos\Arduino\libraries\LiquidCrystal_I2C/LiquidCrystal_I2C.h:51:12: note: in expansion of macro ‘B00000100’
#define En B00000100 // Enable bit
^~~~~~~~~
Hola. Solo atiendo consultas en https://parzibyte.me/#contacto
Saludos!