Dance Dance Revolution program for main mbed

Dependencies:   4DGL-uLCD-SE SDFileSystem mbed-rtos mbed wave_player

main.cpp

Committer:
wliu88
Date:
2016-04-29
Revision:
0:8a02ac09eae0

File content as of revision 0:8a02ac09eae0:


//FULL GAME (MAIN MBED)

#include "mbed.h"
#include "uLCD_4DGL.h"
#include "rtos.h"
#include "SDFileSystem.h"
#include <string>
#include <vector>
#include "joystick.h"
#include "background.h"
#include "arrows.h"
#include "releaser.h"
#include "songs.h"


Mutex mutex;
Mutex m;
Mutex arm;
uLCD_4DGL uLCD2(p9,p10,p16); // serial tx, serial rx, reset pin;
uLCD_4DGL uLCD(p28,p27,p29);
SDFileSystem sd(p5, p6, p7, p8, "sd");
//InterruptIn pb1(p22);
//InterruptIn pb2(p21);
volatile bool up1 = false;
volatile bool down1 = false;
volatile bool left1 = false;
volatile bool right1 = false;
volatile bool fire1 = false;
volatile bool up2 = false;
volatile bool down2 = false;
volatile bool left2 = false;
volatile bool right2 = false;
volatile bool fire2 = false;
volatile int song1 = 0;
volatile int song2 = 0;
Nav_Switch js1( p12, p14, p13, p15, p11, &up1, &down1, &left1, &right1, &fire1,&song1); //Nav_Switch(PinName up,PinName down,PinName left,PinName right,PinName fire);
Nav_Switch js2( p23, p25, p24, p21, p22, &up2, &down2, &left2, &right2, &fire2,&song2); //Nav_Switch(PinName up,PinName down,PinName left,PinName right,PinName fire);
// variables used for controlling the process
volatile bool pushed1 = false;
volatile bool pushed2 = false;
volatile bool selected1 = false;
volatile bool selected2 = false;
volatile bool process1 = false;
volatile bool process2 = false;
volatile bool finished1 = false;
volatile bool finished2 = false;
ArrowReleaser ar = ArrowReleaser();
ArrowReleaser ar2 = ArrowReleaser();
double nextdelay = 1.0;
int indx = 0;
int chk;
int chk2;
volatile int counter = 0;
volatile int counter2 = 0;
volatile bool empty = false;
volatile bool scoreScreen = false;
DigitalOut songSelected(p19);
DigitalOut specificSong(p20);




vector<string> filenames;

// helper function
// read files names in dir and put them in the variable "filenames"
void read_file_names(char *dir)
{
    DIR *dp;
    struct dirent *dirp;
    dp = opendir(dir);
    //read all directory and file names in current directory into filename vector
    while((dirp = readdir(dp)) != NULL) {
        string filename = string(dirp->d_name);
        if ((filename[0] >= 97 && filename[0] <=122) || (filename[0] >= 65 && filename[0] <=90)) {
            filenames.push_back(filename);
        }
    }
    closedir(dp);
}

void uLCD_thread(void const *args) {
    
    // 1. title screen
    mutex.lock();
    //uLCD.cls();
    //uLCD.reset();
    uLCD.textbackground_color(BLACK);
    uLCD.color(RED);
    uLCD.locate(4,0);  
    uLCD.printf("Dance Dance");
    uLCD.locate(4,1);
    uLCD.printf("Revolution!");
    uLCD.locate(6,15);
    uLCD.printf("Player 1");
    mutex.unlock();
    while(!pushed1) {
        mutex.lock();
        uLCD.locate(4,7);
        uLCD.printf("Press CENTER");
        mutex.unlock();
        Thread::wait(1000);
        mutex.lock();
        uLCD.locate(4,7);
        uLCD.printf("            ");
        mutex.unlock(); 
        pushed1 = fire1;   
    }

    // 2. ready screen
    mutex.lock();
    uLCD.cls();
    uLCD.locate(0,7);
    uLCD.printf("Player 1 is ready!");
    mutex.unlock();
    Thread::wait(1000);
    while(!pushed2) {
        mutex.lock();
        uLCD.locate(0,9); 
        uLCD.printf("Wait player 2...");
        mutex.unlock();
    }

    // 3. song selection screen
    while(!process1) {
        Thread::yield();
    }
    mutex.lock();
    uLCD.cls();
    uLCD.printf("Select a song");
    mutex.unlock();
    fire1 = false;
    while(!selected1 || !selected2) {
        for (int i = 0; i < filenames.size(); i++) {
            mutex.lock();
            if (i == song1) {
                uLCD.color(RED);
            } else {
                uLCD.color(GREEN);
            }
            uLCD.locate(0,i+2);
            uLCD.printf("%s\n\r", filenames[i].c_str());
            uLCD.locate(16,i+2);
            uLCD.printf("  ");
            if (i == song2) {
                uLCD.color(BLUE);
                uLCD.locate(16,i+2);
                uLCD.printf("<-");
            }
            mutex.unlock();
        }
        if (selected1) {
            mutex.lock();
            uLCD.locate(0,8);
            uLCD.color(RED);
            uLCD.printf("Ready!");
            mutex.unlock();
        }
        selected1 = fire1;
    }


    // 5. count down
    mutex.lock();
    uLCD.cls();
    uLCD.color(RED);
    uLCD.printf("%s\n\r", filenames[song1].c_str());
    uLCD.locate(0,1);
    uLCD.printf("is picked");
    mutex.unlock();
    while(!process2) {
        Thread::yield();
    }
    mutex.lock();
    uLCD.cls();
    uLCD.text_width(4); //4X size text
    uLCD.text_height(4);
    mutex.unlock();
    uLCD.color(RED);
    for (int i=5; i>=0; --i) {
        mutex.lock();
        uLCD.locate(1,2);
        uLCD.printf("%2D",i);
        mutex.unlock();
        Thread::wait(1000);
    }
    finished1 = true;
}

void uLCD2_thread(void const *args) {
    
    // 1. title screen
    mutex.lock();
    //uuLCD2.cls();
    //uuLCD2.reset();
    uLCD2.textbackground_color(BLACK);
    uLCD2.color(BLUE);
    uLCD2.locate(4,0);  
    uLCD2.printf("Dance Dance");
    uLCD2.locate(4,1);
    uLCD2.printf("Revolution!");
    uLCD2.locate(6,15);
    uLCD2.printf("Player 2");
    mutex.unlock();
    while(!pushed2) {
        mutex.lock();
        uLCD2.locate(4,7);
        uLCD2.printf("Press CENTER");
        mutex.unlock();
        wait(1);
        mutex.lock();
        uLCD2.locate(4,7);
        uLCD2.printf("            ");
        mutex.unlock();   
        pushed2 = fire2; 
    }

    // 2. ready screen
    mutex.lock();
    uLCD2.cls();
    uLCD2.locate(0,7);
    uLCD2.printf("Player 2 is ready!");
    mutex.unlock();
    Thread::wait(1000);
    while(!pushed1){
        mutex.lock();
        uLCD2.locate(0,9); 
        uLCD2.printf("Wait player 1...");
        mutex.unlock();
    }

    // 3. song selection screen
    Thread::wait(1000);
    process1 = true;
    mutex.lock();
    uLCD2.cls();
    uLCD2.printf("Select a song");
    mutex.unlock();
    fire2 = false;
    while(!selected2 || !selected1) {
        for (int i = 0; i < filenames.size(); i++) {
            mutex.lock();
            if (i == song2) {
                uLCD2.color(BLUE);
            } else {
                uLCD2.color(GREEN);
            }
            uLCD2.locate(0,i+2);
            uLCD2.printf("%s\n\r", filenames[i].c_str());
            uLCD2.locate(16,i+2);
            uLCD2.printf("  ");
            // add a marker to notify player 2 about player 1's selection
            if (i == song1) {
                uLCD2.color(RED);
                uLCD2.locate(16,i+2);
                uLCD2.printf("<-");
            }
            mutex.unlock();
        }
        if (selected2) {
            mutex.lock();
            uLCD2.locate(0,8);
            uLCD2.color(BLUE);
            uLCD2.printf("Ready!");
            mutex.unlock();
        }
        selected2 = fire2;
    }

    // 5. count down
    mutex.lock();
    uLCD2.cls();
    uLCD2.color(BLUE);
    uLCD2.printf("%s\n\r", filenames[song1].c_str());
    uLCD2.locate(0,1);
    uLCD2.printf("is picked");
    mutex.unlock();
    Thread::wait(3000);
    process2 = true;
    mutex.lock();
    uLCD2.cls();
    uLCD2.text_width(4); //4X size text
    uLCD2.text_height(4);
    mutex.unlock();
    uLCD2.color(BLUE);
    for (int i=5; i>=0; --i) {
        mutex.lock();
        uLCD2.locate(1,2);
        uLCD2.printf("%2D",i);
        mutex.unlock();
        Thread::wait(1000);
    }
    finished2 = true;
}

//GAME

void arrowreleasing_thread1(void const *args) {
    Thread::wait(100);
    if(!song1){
        while(1){
            chk = 0; chk2 =0;
            while(!chk && !chk2){
                arm.lock();
                m.lock();
                chk = ar.ReleaseArrow(DemoArray2,indx,2);
                m.unlock();
                arm.unlock();
                Thread::wait(100);
            }
            indx++;
            if(indx == 53){
                arm.lock();
                ar.setTermStatus(1);
                arm.unlock();
                break;
            }
            nextdelay = DemoArray2[indx-1].getDelay();
            Thread::wait(nextdelay*1000);         
        }
    }
    else{
        while(1){
            chk = 0; chk2 =0;
            while(!chk && !chk2){
                arm.lock();
                m.lock();
                chk = ar.ReleaseArrow(DemoArray,indx,2);
                m.unlock();
                arm.unlock();
                Thread::wait(100);
            }
            indx++;
            if(indx == 53){
                arm.lock();
                ar.setTermStatus(1);
                arm.unlock();
                break;
            }
            nextdelay = DemoArray[indx-1].getDelay();
            Thread::wait(nextdelay*1000);         
        }
    }
}

void arrowdrawing_thread1(void const *args){
    int term;
    while(!scoreScreen){
        for(int i=0; i< 5; i++){
            arm.lock();
            if(ar.ActiveArrows[i].getActive()){
                m.lock();
                term = ar.ActiveArrows[i].update(2);
                m.unlock();
                if(term){
                    ar.ActiveArrows[i].setActive(0);
                    m.lock();
                    setup_goal_arrows();
                    uLCD.locate(0,0);
                    uLCD.printf("%d",counter);
                    setup_goal_arrows2();
                    uLCD2.locate(0,0);
                    uLCD2.printf("%d",counter2);
                    m.unlock();
                    term = 0;
                }
            }
            arm.unlock();  
        }
        /*arm.lock();
        if(empty && ar.getTermStatus()){
           arm.unlock();
           //Song has ended and all arrows have ended
           scoreScreen = true;
           break; 
        }*/
    }
    
}


void joystick2_thread(void const *args) {
    while(!scoreScreen){
      if(left2){
        left2 = false;
        for(int i=0; i < 5; i++){
            arm.lock();
            if(ar.ActiveArrows[i].getActive() && ar.ActiveArrows[i].getType() == 0 && abs(ar.ActiveArrows[i].curry - refarrow_left_y) <= 10){
                arm.unlock();
                counter2++;
                m.lock();
                uLCD2.locate(0,0);
                uLCD2.printf("%d",counter2);
                m.unlock();
                break;    
            }
            arm.unlock();
        }
        m.lock();
        uLCD2.circle(refarrow_left_x,refarrow_left_y,10,0x00FF00);
        m.unlock();
        wait(0.04);
        m.lock();
        uLCD2.circle(refarrow_left_x,refarrow_left_y,10,0x000000);
        uLCD2.locate(0,0);
        uLCD2.printf("%d",counter2);
        m.unlock();
        }
        if(right2){
            right2 = false;
            for(int i=0; i < 5; i++){
                arm.lock();
                if(ar.ActiveArrows[i].getActive() && ar.ActiveArrows[i].getType() == 3 && abs(ar.ActiveArrows[i].curry - refarrow_right_y) <= 10){
                    arm.unlock();
                    counter2++;
                    m.lock();
                    uLCD2.locate(0,0);
                    uLCD2.printf("%d",counter2);
                    m.unlock();
                    break;    
                }
                arm.unlock();
            }
            m.lock();
            uLCD2.circle(refarrow_right_x,refarrow_right_y,10,0x00FF00);
            m.unlock();
            wait(0.04);
            m.lock();
            uLCD2.circle(refarrow_right_x,refarrow_right_y,10,0x000000);
            uLCD2.locate(0,0);
            uLCD2.printf("%d",counter2);
            m.unlock();
        }
        if(up2){
            up2 = false;
            for(int i=0; i < 5; i++){
                arm.lock();
                if(ar.ActiveArrows[i].getActive() && ar.ActiveArrows[i].getType() == 1 && abs(ar.ActiveArrows[i].curry - refarrow_up_y) <= 10){
                    arm.unlock();
                    counter2++;
                    m.lock();
                    uLCD2.locate(0,0);
                    uLCD2.printf("%d",counter2);
                    m.unlock();
                    break;    
                }
                arm.unlock();
            }
            m.lock();
            uLCD2.circle(refarrow_up_x,refarrow_up_y,10,0x00FF00);
            m.unlock();
            wait(0.04);
            m.lock();
            uLCD2.circle(refarrow_up_x,refarrow_up_y,10,0x000000);
            uLCD2.locate(0,0);
            uLCD2.printf("%d",counter2);
            m.unlock();
        }
        if(down2){
            down2 = false;
            for(int i=0; i < 5; i++){
                arm.lock();
                if(ar.ActiveArrows[i].getActive() && ar.ActiveArrows[i].getType() == 2 && abs(ar.ActiveArrows[i].curry - refarrow_down_y) <= 10){
                    arm.unlock();
                    counter2++;
                    m.lock();
                    uLCD2.locate(0,0);
                    uLCD2.printf("%d",counter2);
                    m.unlock();
                    break;    
                }
                arm.unlock();
            }
            m.lock();
            uLCD2.circle(refarrow_down_x,refarrow_down_y,10,0x00FF00);
            m.unlock();
            wait(0.04);
            m.lock();
            uLCD2.circle(refarrow_down_x,refarrow_down_y,10,0x000000);
            uLCD2.locate(0,0);
            uLCD2.printf("%d",counter2);
            m.unlock();
        }
        Thread::wait(10);  
        
    }    
}


int main()
{
    
    uLCD.baudrate(3000000);
    uLCD2.baudrate(3000000);
    read_file_names("/sd/wavfiles");
    Thread thread1(uLCD_thread);
    Thread thread2(uLCD2_thread);
    while(true)
    {
        if(finished1 && finished2){
            thread1.terminate();
            thread2.terminate();
            uLCD.cls();
            uLCD2.cls();
            break;
        }
    }
    
    songSelected = 1;
    specificSong = song1;
    
    //GAME
    uLCD.baudrate(8000);
    uLCD2.baudrate(8000);
    uLCD.color(GREEN);
    uLCD2.color(GREEN);
    uLCD.locate(0,0);
    uLCD.printf("%d",counter);
    setup_lining();
    setup_goal_arrows();
    uLCD2.locate(0,0);
    uLCD2.printf("%d",counter);
    setup_lining2();
    setup_goal_arrows2();
    wait(1);
    Thread t1(arrowreleasing_thread1);
    t1.set_priority(osPriorityRealtime);
    Thread t2(arrowdrawing_thread1);
    Thread t3(joystick2_thread);
    t3.set_priority(osPriorityHigh);
    while(1){
        
        if(left1){
            left1 = false;
            for(int i=0; i < 5; i++){
                arm.lock();
                if(ar.ActiveArrows[i].getActive() && ar.ActiveArrows[i].getType() == 0 && abs(ar.ActiveArrows[i].curry - refarrow_left_y) <= 10){
                    arm.unlock();
                    counter++;
                    m.lock();
                    uLCD.locate(0,0);
                    uLCD.printf("%d",counter);
                    m.unlock();
                    break;    
                }
                arm.unlock();
            }
            m.lock();
            uLCD.circle(refarrow_left_x,refarrow_left_y,10,0x00FF00);
            m.unlock();
            wait(0.04);
            m.lock();
            uLCD.circle(refarrow_left_x,refarrow_left_y,10,0x000000);uLCD.locate(0,0);
            uLCD.locate(0,0);
            uLCD.printf("%d",counter);
            m.unlock();
        }
        if(right1){
            right1 = false;
            for(int i=0; i < 5; i++){
                arm.lock();
                if(ar.ActiveArrows[i].getActive() && ar.ActiveArrows[i].getType() == 3 && abs(ar.ActiveArrows[i].curry - refarrow_right_y) <= 10){
                    arm.unlock();
                    counter++;
                    m.lock();
                    uLCD.locate(0,0);
                    uLCD.printf("%d",counter);
                    m.unlock();
                    break;    
                }
                arm.unlock();
            }
            m.lock();
            uLCD.circle(refarrow_right_x,refarrow_right_y,10,0x00FF00);
            m.unlock();
            wait(0.04);
            m.lock();
            uLCD.circle(refarrow_right_x,refarrow_right_y,10,0x000000);
            uLCD.locate(0,0);
            uLCD.printf("%d",counter);
            m.unlock();
        }
        if(up1){
            up1 = false;
            for(int i=0; i < 5; i++){
                arm.lock();
                if(ar.ActiveArrows[i].getActive() && ar.ActiveArrows[i].getType() == 1 && abs(ar.ActiveArrows[i].curry - refarrow_up_y) <= 10){
                    arm.unlock();
                    counter++;
                    m.lock();
                    uLCD.locate(0,0);
                    uLCD.printf("%d",counter);
                    m.unlock();
                    break;    
                }
                arm.unlock();
            }
            m.lock();
            uLCD.circle(refarrow_up_x,refarrow_up_y,10,0x00FF00);
            m.unlock();
            wait(0.04);
            m.lock();
            uLCD.circle(refarrow_up_x,refarrow_up_y,10,0x000000);
            uLCD.locate(0,0);
            uLCD.printf("%d",counter);
            m.unlock();
        }
        if(down1){
            down1 = false;
            for(int i=0; i < 5; i++){
                arm.lock();
                if(ar.ActiveArrows[i].getActive() && ar.ActiveArrows[i].getType() == 2 && abs(ar.ActiveArrows[i].curry - refarrow_down_y) <= 10){
                    arm.unlock();
                    counter++;
                    m.lock();
                    uLCD.locate(0,0);
                    uLCD.printf("%d",counter);
                    m.unlock();
                    break;    
                }
                arm.unlock();
            }
            m.lock();
            uLCD.circle(refarrow_down_x,refarrow_down_y,10,0x00FF00);
            m.unlock();
            wait(0.04);
            m.lock();
            uLCD.circle(refarrow_down_x,refarrow_down_y,10,0x000000);
            uLCD.locate(0,0);
            uLCD.printf("%d",counter);
            m.unlock();
        }
        if(fire1){
            //nothing  
        }
        arm.lock();
        if(ar.getTermStatus()){
           empty = true;
           for(int i=0; i < 5; i++){
                if(ar.ActiveArrows[i].getActive()) {
                    empty = false;
                    break;
                }   
            }
            if(empty) {
                scoreScreen = true;
                uLCD.cls();
                uLCD2.cls();
                break;
            }
        }
        arm.unlock();
        wait(0.01);
    }
    
    //End of game
    uLCD.cls();
    uLCD2.cls();
    if(counter > counter2){
        end_screen();
        uLCD.locate(6,6);
        uLCD.color(GREEN);
        uLCD.printf("YOU WIN!\n   PLAYER 1 WINS!");
        uLCD2.locate(5,6);
        uLCD2.color(RED);
        uLCD2.printf("YOU LOSE!\n   PLAYER 1 WINS!");
        end_screen();
    }
    else if (counter2 > counter) {
        end_screen();
        uLCD.locate(5,6);
        uLCD.color(RED);
        uLCD.printf("YOU LOSE!\n   PLAYER 2 WINS!");
        uLCD2.locate(6,6);
        uLCD.color(GREEN);
        uLCD2.printf("YOU WIN!\n   PLAYER 2 WINS!");
        end_screen();
    }
    else {
        end_screen();
        uLCD.locate(7,7);
        uLCD.printf("DRAW");
        uLCD2.locate(7,7);
        uLCD2.printf("DRAW");
        end_screen();
    }
    wait(5);
    uLCD.cls();
    uLCD2.cls();
    end_screen();
    uLCD.locate(6,6);
    uLCD.color(GREEN);
    uLCD.printf("Thanks\n   for playing!");
    uLCD2.locate(6,6);
    uLCD2.color(GREEN);
    uLCD2.printf("Thanks\n   for playing!");
    end_screen();
}