#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#define doIntroShow 1
#define numberOfWinTexts 7
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW //MD_MAX72XX::PAROLA_HW //MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
#define FLAP_LEFT 2
#define FLAP_RIGHT 3
#define BTNmode 4
#define BTNenter 5
#define buzzer 6
#define BTNdelay 150
#define max_modes 7
byte MAXintro=0;
byte MAXmenu=0;
byte MAXnames=0;
int PTRmenu=0; //ready to add one for the first time
int PTRnames=0; //
byte Score[2]={0,0};
String namesL[9]={"Player 1","Dad","Jasmine","Jasmine","Mum","Dad","Mum","Jasmine","Guest"};
String namesR[9]={"Player 2","Jasmine","Dad","Mum","Jasmine","Mum","Dad","Guest","Jasmine"};
String wintexts[10]={"is the winner!","Reigns supreme","is just fantastic","wins again!","is simply the best..","is the champion..","is an amazing winner"};
bool gameOn=0;
bool STATUS_bootmode=0;
// Hardware SPI connection
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
struct sCatalog
{
textEffect_t effect; // text effect to display
const char * psz; // text string nul terminated
uint16_t speed; // speed multiplier of library default
uint16_t pause; // pause multiplier for library default
};
sCatalog ARYintro[] =
{
{ PA_SCROLL_LEFT, "Badminton", 5, 0}, //0
{ PA_SCROLL_DOWN, "by Dad", 5, 0 }, //1
{ PA_SCROLL_LEFT, "* Let's get ready to play Jasmine *", 5, 0 }, //2
{ PA_SCROLL_LEFT, "Player Select", 5, 0 }, //3
{ PA_SCROLL_LEFT, "Confirm with ENTER", 5, 0 }, //4
{ PA_SCROLL_LEFT, "Game on", 5, 1 } //5
};
sCatalog ARYmenu[] =
{
{ PA_SCROLL_LEFT, "START", 4, 1 },
{ PA_SCROLL_LEFT, "PLAYER", 5, 1 },
{ PA_SCROLL_LEFT, "RESET", 5, 1 },
{ PA_SCROLL_LEFT, "CONTINUE", 5, 1 },
{ PA_SCROLL_LEFT, "WINNER", 5,3 } // 4 /Winner Settings
};
sCatalog ARYnames[] =
{
{ PA_SCROLL_LEFT, "Player1 v Player2", 5, 1 },
{ PA_SCROLL_LEFT, "Dad v Jasmine", 5, 1 },
{ PA_SCROLL_LEFT, "Jasmine v Dad", 5, 1 },
{ PA_SCROLL_LEFT, "Jasmine v Mum", 5, 1 },
{ PA_SCROLL_LEFT, "Mum v Jasmine", 5, 1 },
{ PA_SCROLL_LEFT, "Dad v Mum", 5, 1 },
{ PA_SCROLL_LEFT, "Mum v Dad", 5, 1 },
{ PA_SCROLL_LEFT, "Jasmine v Guest", 5, 1 },
{ PA_SCROLL_LEFT, "Guest v Jasmine", 5, 1 }
};
void setup() {
int lp=0;
Serial.begin(115200);
P.begin();
for (uint8_t i=0; i<ARRAY_SIZE(ARYintro); i++)
{
ARYintro[i].speed *= P.getSpeed();
ARYintro[i].pause *= 500;
}
for (uint8_t i=0; i<ARRAY_SIZE(ARYmenu); i++)
{
ARYmenu[i].speed *= P.getSpeed();
ARYmenu[i].pause *= 500;
}
for (uint8_t i=0; i<ARRAY_SIZE(ARYnames); i++)
{
ARYnames[i].speed *= P.getSpeed();
ARYnames[i].pause *= 500;
}
MAXintro=ARRAY_SIZE(ARYintro)-1;
MAXmenu=ARRAY_SIZE(ARYmenu)-1;
MAXnames=ARRAY_SIZE(ARYnames)-1;
pinMode(FLAP_LEFT,INPUT);
pinMode(FLAP_RIGHT,INPUT);
pinMode(BTNmode,INPUT);
pinMode(BTNenter,INPUT);
pinMode(buzzer,OUTPUT);
randomSeed(analogRead(0));
gameOn=false;
}
void loop() {
int lp;
if (STATUS_bootmode==0) {
if (doIntroShow==1) {
for (lp=0;lp<3;lp++) {
Serial.println("TITLE "+String(lp));
// set up new animation
P.displayText(ARYintro[lp].psz, PA_CENTER, ARYintro[lp].speed, ARYintro[lp].pause, ARYintro[lp].effect, ARYintro[lp].effect);
while (P.displayAnimate()!=true) {}
delay(1000);
}
}
showMenu(0);
}
if (digitalRead(FLAP_LEFT)!=0) {
Serial.println("LEFT");
if (gameOn) {
Score[0]++;
displayScore();
if (Score[0]==21) {
winRoutine(0);
}
} else {
buzz();
}
delay(BTNdelay*2);
}
if (digitalRead(FLAP_RIGHT)!=0) {
Serial.println("RIGHT");
if (gameOn) {
Score[1]++;
displayScore();
if (Score[1]==21) {
winRoutine(1);
}
} else {
buzz();
}
delay(BTNdelay*2);
}
if (digitalRead(BTNmode)!=0) {
PTRmenu++;
if (PTRmenu>MAXmenu) {
PTRmenu=0;
}
Serial.println("Mode "+String(PTRmenu));
P.displayClear();
showMenu(PTRmenu);
delay(BTNdelay);
}
if (digitalRead(BTNenter)!=0) {
Serial.println("Enter");
switch (PTRmenu) {
case 0: //This is START GAME
P.displayClear();
showIntro(5); //"Game on" message
delay(1000);
P.displayClear();
gameOn=true;
displayScore();
break;
case 1: //This is Player Select
P.displayClear();
showIntro(3); //Player Select message
P.displayClear();
selectName();
PTRmenu=0;
showMenu(0);
break;
case 2: //This is Reset
P.displayClear();
showIntro(4); //Confirm with ENTER message
if (confWithEnter()==true) {
// it has been confirmed, so reset everything
PTRnames=0;
Score[0]=0;
Score[1]=0;
PTRmenu=0;
gameOn=false;
} else {
PTRmenu=0;
showMenu(0);
}
break;
case 3: //This is Continue
P.displayClear();
gameOn=true;
displayScore();
break;
}
delay(BTNdelay);
}
STATUS_bootmode=1;
}
//****************************************************************************************
void buzz() {
int i;
//output an frequency
for(i=0;i<80;i++)
{
digitalWrite(buzzer,HIGH);
delay(1);//wait for 1ms
digitalWrite(buzzer,LOW);
delay(1);//wait for 1ms
}
}
void winRoutine(int Player) {
char *ptr;
char scr[100];
String temp="";
int wintx=0;
memset(scr,0,100);
wintx=random(0,numberOfWinTexts);
if (Player==0) {
//the person on the left has won
temp=namesL[PTRnames]+" "+wintexts[wintx];
temp.toCharArray(scr,99);
} else {
temp=namesR[PTRnames]+" "+wintexts[wintx];
temp.toCharArray(scr,99);
}
ptr=scr;
P.displayClear();
P.displayText(ptr, PA_LEFT, ARYmenu[4].speed, ARYmenu[4].pause, PA_SCROLL_LEFT, PA_RANDOM);
while (P.displayAnimate()!=true) {}
gameOn=false;
Score[0]=0;
Score[1]=0;
PTRmenu=0;
showMenu(0);
}
void displayScore() {
char *ptr;
char scr[10];
memset(scr,0,10);
sprintf(scr,"%02d %02d",Score[0],Score[1]);
//strcpy(scr,"00 01");
ptr=scr;
P.displayText(ptr, PA_CENTER, 5, 0, 0, 0);
while (P.displayAnimate()!=true) {}
}
void showIntro(byte which) {
P.displayText(ARYintro[which].psz, PA_CENTER, ARYintro[which].speed, ARYintro[which].pause, ARYintro[which].effect, ARYintro[which].effect);
while (P.displayAnimate()!=true) {}
//delay(500);
}
void showMenu(byte which) {
P.displayText(ARYmenu[which].psz, PA_CENTER, ARYmenu[which].speed, ARYmenu[which].pause, ARYmenu[which].effect, 0);
while (P.displayAnimate()!=true) {}
//delay(500);
}
void showName(byte which) {
Serial.println("Showing name "+String(which));
P.displayClear();
P.displayText(ARYnames[which].psz, PA_LEFT, ARYnames[which].speed, ARYnames[which].pause, ARYnames[which].effect, 0);
while (P.displayAnimate()!=true) {}
//delay(500);
}
void selectName() {
bool finished=false;
//At this point, we have shown the title and we need to display the names
showName(PTRnames);
while (finished==false) {
if (digitalRead(BTNenter)!=0) { //we take the name on the screen
finished=true;
delay(BTNdelay);
}
if (finished==false && digitalRead(BTNmode)!=0) { //We need to change the name to the next one.
PTRnames++;
if (PTRnames>MAXnames) {
PTRnames=1;
}
showName(PTRnames);
//Serial.println("Name is "+ARYnames[PTRnames]);
delay(BTNdelay);
}
}
P.displayClear();
}
bool confWithEnter() {
bool finished=false;
bool retval=false;
while (finished==false) {
if (digitalRead(BTNenter)!=0) { //we register the ENTER
finished=true;
retval=true;
delay(BTNdelay);
}
if (digitalRead(BTNmode)!=0) { //we register MODE
finished=true;
retval=false;
delay(BTNdelay);
}
}
return retval;
}