Final Game. Have fun!!! :-)

Dependencies:   4DGL-uLCD-SE PinDetect mbed-rtos mbed

main.cpp

Committer:
aamin33
Date:
2018-05-03
Revision:
6:f99b7d1fd770
Parent:
4:c136aa81f52a

File content as of revision 6:f99b7d1fd770:

#include "mbed.h"
#include "rtos.h"
#include "uLCD_4DGL.h"
#include "SDFileSystem.h"
#include "wave_player.h"
#include "PinDetect.h"
#include <string>

//***** HW and signal setup *****//
Serial bluemod(p28,p27);                                //bluetooth setup

//Pushbuttons
PinDetect pb1(p24);
PinDetect pb2(p23);
PinDetect pb3(p22);
PinDetect pb4(p21);

int pb1Score = 0;
int pb2Score = 0;
int pb3Score = 0;
int pb4Score = 0;

//Setup RGB led using PWM pins and class
DigitalOut redLed(p19);
DigitalOut greenLed(p20);

uLCD_4DGL uLCD(p13, p14, p12);                          // main screen for game

SDFileSystem sd(p5, p6, p7, p8, "sd");

PwmOut speakerPWM(p26);
AnalogOut DACout(p18);
wave_player waver(&DACout, &speakerPWM);

//***** Constants *****//
const int songLength = 100;                             //adjust as needed

//Arrays for notes
int L1[songLength];
int L2[songLength];
int L3[songLength];
int L4[songLength];

int circleAligner = -6;                                 //count for drawing the circles
int value = 0;                                      //keypad input value
int score = 0;                                  //score
int playGame = 1;                                   //game state toggle to start game
int restartGame = 1;                                //game state toggle to restart or quit

char blueIn = '0';                                  //Bluetooth setup
int selectedSong = 0;

FILE *wav_file;                                     // song file

//-----------------------------------------------------------------------------------------------------------------------

void pb1_hit_interrupt(void) {
    if (circleAligner > -1) {
        if (L4[circleAligner] == 1) {
            pb1Score = pb1Score + 1;                    //increment points if tapped correctly
            redLed = 0; 
            greenLed = 1; 
        } else {
            redLed = 1; 
            greenLed = 0;      
        }
    }
    wait(.05);
    redLed = 1;
    greenLed = 0;
}

void pb2_hit_interrupt(void) {
    if (circleAligner > -1) {
        if (L3[circleAligner] == 1) {
            pb2Score = pb2Score + 1; 
            redLed = 0; 
            greenLed = 1; 
        } else {
            redLed = 1; 
            greenLed = 0;        
        }
    }
    wait(.05);
    redLed = 1;
    greenLed = 0;
}

void pb3_hit_interrupt(void) {
    if (circleAligner > -1) {
        if (L2[circleAligner] == 1) {
            pb3Score = pb3Score + 1; 
            redLed = 0; 
            greenLed = 1; 
        } else {
            redLed = 1; 
            greenLed = 0;         
        }
    }
    wait(.05);
    redLed = 1;
    greenLed = 0;
}

void pb4_hit_interrupt(void) {
    if (circleAligner > -1) {
        if (L1[circleAligner] == 1) {
            pb4Score = pb4Score + 1; 
            redLed = 0; 
            greenLed = 1; 
        } else {
            redLed = 1; 
            greenLed = 0; 
        }
    }
    wait(.05);
    redLed = 1;
    greenLed = 0;
}

//-----------------------------------------------------------------------------------------------------------------------

void lcdThread1(void const *args) {
    while(playGame) {
        circleAligner++;
        uLCD.filled_circle(110, 20, 12, BLACK);
        uLCD.filled_circle(110, 50, 12, BLACK);
        uLCD.filled_circle(110, 80, 12, BLACK);
        uLCD.filled_circle(110, 110, 12, BLACK);
        if (circleAligner >= 0) {                       //draw the path of the circles
            if (L1[circleAligner]) {
                uLCD.filled_circle(86, 20, 10, BLACK);
                uLCD.filled_circle(110, 20, 12, BLUE);
            }
            if (L2[circleAligner]) {
                uLCD.filled_circle(86, 50, 10, BLACK);
                uLCD.filled_circle(110, 50, 12, RED);
            }
            if (L3[circleAligner]) {
                uLCD.filled_circle(86, 80, 10, BLACK);
                uLCD.filled_circle(110, 80, 12, GREEN);
            }
            if (L4[circleAligner]) {
                uLCD.filled_circle(86, 110, 10, BLACK);
                uLCD.filled_circle(110, 110, 12, LGREY);
            }
        }
        if (circleAligner >= -1) {
            if (L1[circleAligner + 1]) {
                uLCD.filled_circle(66, 20, 8, BLACK);
                uLCD.filled_circle(86, 20, 10, BLUE);}
            if (L2[circleAligner + 1]) {
                uLCD.filled_circle(66, 50, 8, BLACK);
                uLCD.filled_circle(86, 50, 10, RED);}
            if (L3[circleAligner + 1]) {
                uLCD.filled_circle(66, 80, 8, BLACK);
                uLCD.filled_circle(86, 80, 10, GREEN);
            }
            if (L4[circleAligner + 1]) {
                uLCD.filled_circle(66, 110, 8, BLACK);
                uLCD.filled_circle(86, 110, 10, LGREY);
            }
        }
        if (circleAligner >= -2) {
            if (L1[circleAligner + 2]) {
                uLCD.filled_circle(50, 20, 6, BLACK);
                uLCD.filled_circle(66, 20, 8, BLUE);
            }
            if (L2[circleAligner + 2]) {
                uLCD.filled_circle(50, 50, 6, BLACK);
                uLCD.filled_circle(66, 50, 8, RED);
            }
            if (L3[circleAligner + 2]) {
                uLCD.filled_circle(50, 80, 6, BLACK);
                uLCD.filled_circle(66, 80, 8, GREEN);
            }
            if (L4[circleAligner + 2]) {
                uLCD.filled_circle(50, 110, 6, BLACK);
                uLCD.filled_circle(66, 110, 8, LGREY);
            }
        }
        if (circleAligner >= -3) {
            if (L1[circleAligner + 3]) {
                uLCD.filled_circle(38, 20, 4, BLACK);
                uLCD.filled_circle(50, 20, 6, BLUE);
            }
            if (L2[circleAligner + 3]) {
                uLCD.filled_circle(38, 50, 4, BLACK);
                uLCD.filled_circle(50, 50, 6, RED);
            }
            if (L3[circleAligner + 3]) {
                uLCD.filled_circle(38, 80, 4, BLACK);
                uLCD.filled_circle(50, 80, 6, GREEN);
            }
            if (L4[circleAligner + 3]) {
                uLCD.filled_circle(38, 110, 4, BLACK);
                uLCD.filled_circle(50, 110, 6, LGREY);
            }
        }
        if (circleAligner >= -4) {
            if (L1[circleAligner + 4]) {
                uLCD.filled_circle(30, 20, 2, BLACK);
                uLCD.filled_circle(38, 20, 4, BLUE);
            }
            if (L2[circleAligner + 4]) {
                uLCD.filled_circle(30, 50, 2, BLACK);
                uLCD.filled_circle(38, 50, 4, RED);
            }
            if (L3[circleAligner + 4]) {
                uLCD.filled_circle(30, 80, 2, BLACK);
                uLCD.filled_circle(38, 80, 4, GREEN);
            }
            if (L4[circleAligner + 4]) {
                uLCD.filled_circle(30, 110, 2, BLACK);
                uLCD.filled_circle(38, 110, 4, LGREY);
            }
        }
        if (L1[circleAligner + 5]) {
            uLCD.filled_circle(30, 20, 2, BLUE);
        }
        if (L2[circleAligner + 5]) {
            uLCD.filled_circle(30, 50, 2, RED);
        }
        if (L3[circleAligner + 5]) {
            uLCD.filled_circle(30, 80, 2, GREEN);
        }
        if (L4[circleAligner + 5]) {
            uLCD.filled_circle(30, 110, 2, LGREY);
        }
        uLCD.circle(110, 20, 12, WHITE);                    //draw circles at base
        uLCD.circle(110, 50, 12, WHITE);
        uLCD.circle(110, 80, 12, WHITE);
        uLCD.circle(110, 110, 12, WHITE);
        if(circleAligner >= songLength) {                   //stop game if game ends before songs ends
            playGame = 0;
        }
        Thread::wait(250);
    }
}

//-----------------------------------------------------------------------------------------------------------------------

void musicThread(void const *args) {                        //Thread to play song, song is selected in mainMenu()
    speakerPWM.period(1.0 / 400000.0);
    switch(selectedSong) {
        case 1:
            wav_file = fopen("/sd/GTShake.wav", "r");
            break;
        case 2:
            wav_file = fopen("/sd/DarkHorse.wav", "r");
            break;
        case 3:
            wav_file = fopen("/sd/OneRepublic.wav", "r");
            break;
        case 4:
            wav_file = fopen("/sd/ShakeItOff.wav", "r");
            break;
        default:
            wav_file = fopen("/sd/ShakeItOff.wav", "r");
            break;
    }
    waver.play(wav_file);
    while (playGame) {
        Thread::wait(100);
    }
    fclose(wav_file);
}

//-----------------------------------------------------------------------------------------------------------------------

//Function to read notes from a text file into arrays
//parameters: path of file (string), name of file with no suffix (string)
//Example: readFile("/sd/", "test"); gets data from file /sd/test.txt
// 
void readFile(const string path, const string fileName) {
    char name[64];
    snprintf(name, sizeof(name), "%s%s.txt", path.c_str(), fileName.c_str());
    FILE *fp = fopen(name, "r");
    
    int index = 0;
    int c;
    
    do {
        c = getc(fp);
        if(c != '\n') {
            switch (c) {
                case '1':
                    L1[index] = 1;
                    L2[index] = 0;
                    L3[index] = 0;
                    L4[index] = 0;
                    break;
                case '2':
                    L1[index] = 0;
                    L2[index] = 1;
                    L3[index] = 0;
                    L4[index] = 0;
                    break;
                case '3':
                    L1[index] = 0;
                    L2[index] = 0;
                    L3[index] = 1;
                    L4[index] = 0;
                    break;
                case '4':
                    L1[index] = 0;
                    L2[index] = 0;
                    L3[index] = 0;
                    L4[index] = 1;
                    break;
            }
            index++;
        }
    } while ((c!=EOF) && (index < songLength));
    
    fclose(fp);
}

//Gets data for selected song
void readSong(int selection) {
    switch(selection) {
        case 1:
            readFile("/sd/", "GTShake");
            break;
        case 2:
            readFile("/sd/", "DarkHorse");
            break;
        case 3:
            readFile("/sd/", "OneRepublic");
            break;
        case 4:
            readFile("/sd/", "ShakeItOff");
            break;
        default:
            readFile("/sd/", "ShakeItOff");
            break;
    }
}

//-----------------------------------------------------------------------------------------------------------------------

void bootMainMenu() {   
    uLCD.display_control(PORTRAIT_R);
    uLCD.locate(5,0);
    uLCD.printf("Welcome!");
    uLCD.locate(2,2);
    uLCD.printf("Choose a song\n\n");
    uLCD.printf("1: GTShake\n\n");
    uLCD.printf("2: DarkHorse\n\n");
    uLCD.printf("3: OneRepublic\n\n");
    uLCD.printf("4: ShakeItOff\n\n");
   
    int startGame = 0;
    
    //reset variables used in game
    playGame = 1;
    circleAligner = -6;
    blueIn = '0';
    score = 0;
    pb1Score = 0;
    pb2Score = 0;
    pb3Score = 0;
    pb4Score = 0;
    
    selectedSong = 0;
    
    while (!startGame) {                            //Loop until a valid song is selected
        while (bluemod.readable()) {
            blueIn = bluemod.getc();                    //Read bluetooth input and select song.
            switch(blueIn) {
                case '1':
                    selectedSong = 1;
                    break;
                case '2':
                    selectedSong = 2;
                    break;
                case '3':
                    selectedSong = 3;
                    break;
                case '4':
                    selectedSong = 4;
                    break;
            }
            break;                          //Only read 1 character at a time
        }
        if(selectedSong >= 1 && selectedSong <= 4) {            //Start game once song is selected
            startGame = 1;
        }
    }
    uLCD.cls();
}

//-----------------------------------------------------------------------------------------------------------------------

void bootEndScreen() {
    uLCD.cls();
    uLCD.display_control(PORTRAIT_R);
    score = pb1Score + pb2Score + pb3Score + pb4Score;
    uLCD.printf("Score: %d\n", score);
    uLCD.printf("Percent Correct:\n%04.1f\n\n", (float) score / (float) songLength * 100);
    uLCD.printf("1: Play Again\n");
    uLCD.printf("2: Quit.");
    blueIn = '0';
    while (restartGame < 0) {                           //Loop waiting for bluetooth input
        while (bluemod.readable()) {
            blueIn = bluemod.getc();                    //Read bluetooth input and select song.
            if (blueIn == '1') {
                restartGame = 1;                        //if 1 go back to main menu
                break;
            } else if (blueIn == '2') {
                restartGame = 0;                        //if 2 end game
                break;
            }
        }
    }
}

//-----------------------------------------------------------------------------------------------------------------------

int main() {
    uLCD.baudrate(3000000);

    pb1.mode(PullUp);
    pb2.mode(PullUp);
    pb3.mode(PullUp);
    pb4.mode(PullUp);
    wait(0.001);
    pb1.attach_deasserted(&pb1_hit_interrupt);
    pb2.attach_deasserted(&pb2_hit_interrupt);
    pb3.attach_deasserted(&pb3_hit_interrupt);
    pb4.attach_deasserted(&pb4_hit_interrupt);
    pb1.setSampleFrequency();
    pb2.setSampleFrequency();
    pb3.setSampleFrequency();
    pb4.setSampleFrequency();

    while(restartGame) {
        bootMainMenu();                             //Game stays at menu until player chooses song through bluetooth
        readSong(selectedSong);                         //create note arrays based on chosen song
        
        uLCD.display_control(LANDSCAPE_R);              //Orient the game in landscape mode.
        
        Thread thread1(lcdThread1);                     //thread that displays the circles
        Thread thread2(musicThread);                    //thread that plays the song
                        
        while (playGame) {   
            Thread::wait(10);
        }
        
        thread2.terminate();                        //End music thread
        
        playGame = 1;                           //reset game state switches
        restartGame = -1;
        
        bootEndScreen();                            //Game stays at end screen until player restarts or quits
        
        uLCD.cls();
    }
}