//CÓMO LEER EL BOTÓN
//CÓMO IMPLEMENTARLO EN FÍSICO - EL MANDO.
//CÓMO IMPLEMENTAR EL JUEGO EN 2 JUGADORES.
#include <Adafruit_NeoPixel.h>
#include <SoftwareSerial.h>
#define PIN_NEO_PIXEL 13
#define NUM_PIXELS 64
#define pinBuzzer 1
Adafruit_NeoPixel NeoPixel(NUM_PIXELS, PIN_NEO_PIXEL, NEO_GRB + NEO_KHZ800);
int state = 0;
int keylvl = 0;
int currentScore = 0;
int score = 0;
int posPaddleX1 = 3;
int posPaddleY1 = 7;
int posPaddleX2 = 3;
int posPaddleY2 = 0;
int posBallX = 5;
int posBallY = 5;
int dirBallX = 1;
int dirBallY = -1;
/*
Detectar el número de jugadores y poner el juego dependiendo de ello.
El mando 1 debe ser el encargado de elegir el nivel del juego y de darle start.
Para dos jugadores, visualizar cuál pierde y cuál gana.
Utilizar un bit de paradad y un bit de paridad.
IDN - COMANDO PARA DETECTAR SI HAY ALGÚN MANDO CONECTADO.
SENSE:PADDLE - SOLICITAR LA POSICIÓN DE LA PALETA CON UNA CADENA ENTRE 0 - 255.
SENSE:START - SOLICITAR EL ESTADO DEL BOTÓN - DEVUELVE CERO SI NO SE HA PRESIONADO. UNO EN C.C.
*/
//MATRIZ BIDIMENSIONAL CON LAS TIPOGRAFÍAS
char level_font[10][8]={
{0x00, 0x62, 0x42, 0x4A, 0x42, 0x46, 0x00, 0x00}, //1
{0x00, 0x62, 0x42, 0x6A, 0x22, 0x66, 0x00, 0x00}, //2
{0x00, 0x62, 0x42, 0x6A, 0x42, 0x66, 0x00, 0x00}, //3
{0x00, 0x62, 0x62, 0x4A, 0x42, 0x46, 0x00, 0x00}, //4
{0x00, 0x62, 0x22, 0x6A, 0x42, 0x66, 0x00, 0x00}, //5
{0x00, 0x62, 0x22, 0x2A, 0x62, 0x66, 0x00, 0x00}, //6
{0x00, 0x62, 0x42, 0x6A, 0x42, 0x46, 0x00, 0x00}, //7
{0x00, 0x62, 0x62, 0x0A, 0x62, 0x66, 0x00, 0x00}, //8
{0x00, 0x62, 0x62, 0x6A, 0x42, 0x46, 0x00, 0x00}, //9
{0x81, 0x42, 0x24, 0x18, 0x24, 0x42, 0x81, 0x00}, //PERDIÓ
};
uint8_t lose2[8] =
{0x00, 0x66, 0x66, 0x18, 0x7E, 0x66, 0x66, 0x00};
//Función para plasmar los niveles de juego
void displayLevelSelection(int level);
//Función para actualizar la posición de la bola.
int updateBall();
//SoftwareSerial Mando2 (9, 10);//Mando 2 - RX, TX.
char buffer[100];
char buffer2[100];
char bufferb[100];
int len;
int len2;
int lenb;
int val;
int val2;
int LVL;
int numPlayers = 1;
int playerLost;
int Button;
void Read_Contol1();
void Read_Control2();
int NumPlayers();
void Read_Button();
SoftwareSerial Mando2 (9, 10);//Mando 2: 9 - TX, 10 - RX.
void setup() {
NeoPixel.begin();
Serial.begin(9600);
Serial.print("*IDN1?\r");
Mando2.begin(9600);
Mando2.print("*IDN2?\r");
}
void loop() {
if (state == 0){
Read_Button();
//Se llama la función que lee el mando 1 - encargado de elegir el nivel.
Read_Control1();
LVL = val/31; //Se guarda el nivel de Val del control1.
//Se muestra el nivel seleccionado.
displayLevelSelection(LVL);
//state++; //Se sale del estado de config.
delay(10);
if(Button == 1){ //Prueba.
//Se determina el número de jugadores
numPlayers = NumPlayers();
state++;
//displayLevelSelection(LVL);
delay(1000);
}
}
else if(state == 1){
displayGame();
Read_Control1();
if(numPlayers == 2)
Read_Control2();
playerLost = updateBall();
if(playerLost == 1){
Serial.println("Perdió Jugador 1");
Read_Button();
state++;
}
else if(playerLost == 2){
Serial.println("Perdió Jugador 2");
Read_Button();
state++;
}
}
else if(state == 2)
{
Read_Button();
if(Button == 1)
{
state = 0; //El estado vuelve a cero (Config.)
Serial.println("RST");
NeoPixel.clear();
NeoPixel.show();
posBallX = 5; //Posición de la bola
posBallY = 5;
dirBallX = 1; //Dirección de la bola
dirBallY = -1;
Button = 0;
delay(200);
}
else {
if(playerLost == 1){
displayLevelSelection(9); //Se muestra en la matriz que perdió
delay(100);}
else if(playerLost == 2){
dislose();
delay(200);
}
}
}
delay(500);
}
void displayGame() {
NeoPixel.clear();
//Display paddle Player 1
NeoPixel.setPixelColor(posPaddleY1*8+posPaddleX1, NeoPixel.Color(0, 0, 255));
NeoPixel.setPixelColor(posPaddleY1*8+posPaddleX1+1, NeoPixel.Color(0, 0, 255));
//Display paddle Player 2
if (numPlayers==2) {
NeoPixel.setPixelColor(posPaddleY2*8+posPaddleX2, NeoPixel.Color(255, 0, 0));
NeoPixel.setPixelColor(posPaddleY2*8+posPaddleX2+1, NeoPixel.Color(255, 0, 0));
}
//Display ball
NeoPixel.setPixelColor(posBallY*8+posBallX, NeoPixel.Color(0, 255, 0));
NeoPixel.show();
}
int updateBall() {
///*
posBallX += dirBallX;
posBallY += dirBallY;
//Collision with left & right walls
if (posBallX<0) {
posBallX = 0;
dirBallX = 1;
}
if (posBallX>7) {
posBallX = 7;
dirBallX = -1;
}
//Collision with top wall
if ((posBallY<0) && (numPlayers==1)) {
posBallY = 0;
dirBallY = 1;
}
if(posBallY>7){ //Se valida el eje y cuando la pelota desciende.
posBallY = 7;
dirBallY = -1;
}
if(posBallY<0){ //Se valida el eje y cuando la pelota desciende.
posBallY = 0;
dirBallY = 1;
}
//*/
//Check if collision with paddle Player 1
if (posBallY==7) {
if((posBallX>=posPaddleX1) && (posBallX<posPaddleX1+1)) {
posBallY = 6;
dirBallY = -1;
tone(pinBuzzer, 390,100); //Se genera un tono cuando se golpea la pelota
currentScore++; //Aumentar el contador
Serial.println(currentScore); //Mostrar el puntaje
} else {
return 1;
}
}
//Check if collision with paddle Player 2
if ((posBallY==0) && (numPlayers==2)) {
if((posBallX>=posPaddleX2) && (posBallX<posPaddleX2+1)) {
posBallY = 1;
dirBallY = 1;
tone(pinBuzzer, 390,100); //Se genera un tono cuando se golpea la pelota
currentScore++; //Aumentar el contador
Serial.println(currentScore); //Mostrar el puntaje
} else {
return 2;
}
}
return 0;
}
//Función para seleccionar el nivel
void displayLevelSelection(int level){
NeoPixel.clear();
NeoPixel.show();
for(int r=0; r<8; r++) {
for(int c=0; c<8; c++) {
if ( (level_font[level][r]>>c) & 0x01 ==1) {
NeoPixel.setPixelColor(r*8+c, NeoPixel.Color(239, 190, 0));
}
}
}
NeoPixel.show();
switch (level)
{
case 8: keylvl = 740; break; //Mayor velocidad (64260 pulsos)
case 7: keylvl = 750; break;
case 6: keylvl = 800; break;
case 5: keylvl = 1100; break;
case 4: keylvl = 1500; break;
case 3: keylvl = 2000; break;
case 2: keylvl = 2500; break;
case 1: keylvl = 3000; break;
case 0: keylvl = 3500; break; //Menor velocidad (61500 pulsos)
}
}
int NumPlayers(){
int conta = 0;
Serial.print("SENSE:PADDLE?\r");
len = Serial.readBytesUntil('\r', buffer, sizeof(buffer));
if(len>0){
conta ++;
}
Mando2.print("SENSE:PADDLE?\r");
len2 = Mando2.readBytesUntil('\r', buffer2, sizeof(buffer2));
if (len2>0) {
conta++;
}
return conta;
}
void Read_Control1(){
Serial.print("SENSE:PADDLE?\r");
len = Serial.readBytesUntil('\r', buffer, sizeof(buffer));
if (len>0) {
buffer[len]=0;
val = atoi(buffer);
posPaddleX1 = val/38;
//Serial.println(posPaddleX1);
//LVL = val/31;
//Serial.println(LVL);
}
}
void Read_Control2(){
Mando2.print("SENSE:PADDLE?\r");
len2 = Mando2.readBytesUntil('\r', buffer2, sizeof(buffer2));
if (len2>0) {
buffer2[len2]=0;
val2 = atoi(buffer2);
posPaddleX2 = val2/38;
//Serial.print(val2);
}
}
void Read_Button(){
Serial.print("SENSE:START?\r");
lenb = Serial.readBytesUntil('\r', bufferb, sizeof(bufferb));
if (lenb>0) {
buffer[lenb]=0;
Button = atoi(bufferb);
// Serial.print(Button);
}
}
void dislose() {
NeoPixel.clear();
for (int r = 0; r < 8; r++) {
for (int c = 0; c < 8; c++) {
if (bitRead(lose2[r], 7 - c)) {
NeoPixel.setPixelColor(r * 8 + c, NeoPixel.Color(255, 0, 0));
}
}
}
NeoPixel.show();
}