Mbed Galaga Game

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

main.cpp

Committer:
amostafa9
Date:
2016-03-14
Revision:
0:c4b6bb8c2bf4

File content as of revision 0:c4b6bb8c2bf4:

#include "mbed.h"
#include "uLCD_4DGL.h"
#include "wave_player.h"
#include "SDFileSystem.h"
//#include "enemies.h"
#include <vector>
#include "rtos.h"
uLCD_4DGL uLCD(p28,p27,p29);
AnalogOut DACout(p18);
DigitalOut vib(p21);
wave_player waver(&DACout);
SDFileSystem sd(p5, p6, p7, p8, "sd"); // mosi, miso, sck, cs
BusOut mbedleds(LED1,LED2,LED3,LED4);
//BusOut/In is faster than multiple DigitalOut/Ins
int playLaser = 0;int playEnemyExplode = 0;int playerExplode = 0;//variables to trigger the speaker to play sounds
void sdcard_thread(void const *argument)//thread to play the sounds
{
    while(1) {

        if(playLaser){//play sound if player fires
            FILE *wave_file;
            wave_file=fopen("/sd/laser.wav","r");
            waver.play(wave_file);
            fclose(wave_file);
            playLaser = 0;
        }
        if(playerExplode) { //play sound if player dies
            FILE *wave_file;
            wave_file=fopen("/sd/Bomb.wav","r");
            waver.play(wave_file);
            fclose(wave_file);
            playerExplode = 0;
        }

        if(playEnemyExplode){//play sound if enemies get hit
            FILE *wave_file;
            wave_file=fopen("/sd/Bombnew.wav","r");
            waver.play(wave_file);
            fclose(wave_file);
            playEnemyExplode = 0;
        }    
        Thread::wait(50);
    }
}

class Nav_Switch
{

public:

    Nav_Switch(PinName up,PinName down,PinName left,PinName right,PinName fire);
    int read();
//boolean functions to test each switch
    bool up();
    bool down();
    bool left();
    bool right();
    bool fire();
//automatic read on RHS
    operator int ();
//index to any switch array style

    bool operator[](int index) {

        return _pins[index];

    };

private:

    BusIn _pins;



};

Nav_Switch::Nav_Switch (PinName up,PinName down,PinName left,PinName right,PinName fire):

    _pins(up, down, left, right, fire)

{

    _pins.mode(PullUp); //needed if pullups not on board or a bare nav switch is used - delete otherwise

    wait(0.001); //delays just a bit for pullups to pull inputs high

}

inline bool Nav_Switch::up()

{

    return !(_pins[0]);

}

inline bool Nav_Switch::down()

{

    return !(_pins[1]);

}

inline bool Nav_Switch::left()

{

    return !(_pins[2]);

}

inline bool Nav_Switch::right()

{

    return !(_pins[3]);

}

inline bool Nav_Switch::fire()

{

    return !(_pins[4]);

}

inline int Nav_Switch::read()

{

    return _pins.read();

}

inline Nav_Switch::operator int ()

{

    return _pins.read();

}

// Declar player dimensions

int playerWidth = 7;

int playerHeight = 3;

int playerDelta = 3;

int playerXpos = 64;

int playerYpos = 113;

#define maxNumPlayerMissiles  5

#define numEnemies  10

//struct for missiles

typedef struct {

    int x;                   ///< The x-coordinate of missile current position

    int y;                   ///< The y-coordinate of missile current position

    int status;   ///< The missile status, see MISSILE_STATUS

} playerMissile; // infomration about missile position and status

//struct for enemies

typedef struct {

    int x;

    int y;

    int size;

    int status;

} enemy;

enemy enemies[numEnemies];//create a struct array of enemies

// initialize the player's position, missile status, draw player, 

void player_draw(int x, int y, int playerColor) {

    uLCD.filled_rectangle(x, y, x+playerWidth, y+playerHeight, playerColor); 

    uLCD.filled_rectangle(x+playerDelta, y-playerDelta, x+playerWidth-playerDelta, y+playerHeight, playerColor);  

}

playerMissile playerMissiles[maxNumPlayerMissiles]; //struct array of player missiles

//function to fire a missile

void player_fire(void){

    playerMissile PM;

    PM.x = playerXpos + (playerWidth/2);

    PM.y = playerYpos-playerDelta;

    PM.status = 1;

    for(int i=0;i<maxNumPlayerMissiles;i++){

        if(playerMissiles[i].status==0){

            playerMissiles[i]=PM;

            break;

        }

    }

}

//function to update all parts of the game

void updateGame(){

    for(int i=0;i<maxNumPlayerMissiles;i++){

        // update all missiles

        if(playerMissiles[i].status == 1){

            uLCD.circle(playerMissiles[i].x,playerMissiles[i].y,1,0x0);

            playerMissiles[i].y-=5;

            uLCD.circle(playerMissiles[i].x,playerMissiles[i].y,1,0xFF0000);

        }

        if(playerMissiles[i].y==0 || playerMissiles[i].status==0){

            uLCD.circle(playerMissiles[i].x,playerMissiles[i].y,1,0x0);

           playerMissiles[i].status = 0;

        }

        //update all enemies

        for(int j=0;j<numEnemies;j++){

            if(playerMissiles[i].status==1 && enemies[j].status==1 && playerMissiles[i].x>enemies[j].x && playerMissiles[i].x<enemies[j].x+enemies[j].size && playerMissiles[i].y>enemies[j].y && playerMissiles[i].y<enemies[j].y+enemies[j].size){

                enemies[j].status = 0;

                playerMissiles[i].status = 0;

                playEnemyExplode=1;

                uLCD.filled_rectangle(enemies[j].x,enemies[j].y,enemies[j].x+enemies[j].size,enemies[j].y+enemies[j].size,0x0);

            }

        }

    }   

}

//function to set initial position of enemies

void enemies_init(void){

    enemies[0].x = 1;enemies[0].y = 1;enemies[0].size = 8;

    enemies[1].x = 26;enemies[1].y = 1;enemies[1].size = 8;

    enemies[2].x = 51;enemies[2].y = 1;enemies[2].size = 8;

    enemies[3].x = 76;enemies[3].y = 1;enemies[3].size = 8;

    enemies[4].x = 101;enemies[4].y = 1;enemies[4].size = 8;

    enemies[5].x = 1;enemies[5].y = 20;enemies[5].size = 8;

    enemies[6].x = 26;enemies[6].y = 20;enemies[6].size = 8;

    enemies[7].x = 51;enemies[7].y = 20;enemies[7].size = 8;

    enemies[8].x = 76;enemies[8].y = 20;enemies[8].size = 8;

    enemies[9].x = 101;enemies[9].y = 20;enemies[9].size = 8;

}

Nav_Switch myNav( p15, p12, p13, p11, p14); //pin order on Sparkfun breakout



int main()

{

    Thread thread1(sdcard_thread);

    int ctr = 0;int distance=5;int vertical = 1;int win = 1;int numDeadEnemies=0;

    //initialize enemy statuses

    enemies[0].status = 1;enemies[1].status = 1;enemies[2].status = 1;enemies[3].status = 1;enemies[4].status = 1;

    enemies[5].status = 1;enemies[6].status = 1;enemies[7].status = 1;enemies[8].status = 1;enemies[9].status = 1;

    enemies_init();

    //draw enemies

    for(int i=0;i<numEnemies;i++){

        uLCD.filled_rectangle(enemies[i].x,enemies[i].y,enemies[i].x+enemies[i].size,enemies[i].y+enemies[i].size,0x00FF00);

    }

    int i;

    while(1) {

        //with pullups a button hit is a "0" - "~" inverts data to leds

        if(ctr%10==0){

            for(i=0;i<numEnemies;i++){

                if(enemies[i].status!=0){

                    //update enemy positions

                    uLCD.filled_rectangle(enemies[i].x,enemies[i].y,enemies[i].x+enemies[i].size,enemies[i].y+enemies[i].size,0x0);

                    if(vertical<0){enemies[i].x+=distance;}else{enemies[i].y+=5;}

                    uLCD.filled_rectangle(enemies[i].x,enemies[i].y,enemies[i].x+enemies[i].size,enemies[i].y+enemies[i].size,0x00FF00);

                }

            }

            if(vertical<0){distance*=-1;}vertical*=-1;

        }

        mbedleds = ~(myNav & 0x0F); //update leds with nav switch direction inputs

       if(myNav.fire()){//fire missile

            vib = 1;

            Thread::wait(100);

            vib=0;

            playLaser = 1;

            player_fire();

            mbedleds = 0x0F; //special all leds on case for fire (center button)

        }

       //or use - if(myNav[4]==0) mbedleds = 0x0F; //can index a switch bit like this

        if(myNav.right() && playerXpos <= 110){//player moves right

            player_draw(playerXpos,playerYpos,0x0);

            playerXpos+=5;

        }

        if(myNav.left() && playerXpos >= 0){//player moves left

            player_draw(playerXpos,playerYpos,0x0);

            playerXpos-=5;

        }

        player_draw(playerXpos,playerYpos,0xFFFF00);//draw the player

        updateGame();

        //check if player has been hit

        for(i=0;i<numEnemies;i++){

            if(enemies[i].status==1 && playerXpos>enemies[i].x && playerXpos<enemies[i].x+enemies[i].size && playerYpos>enemies[i].y && playerYpos<enemies[i].y+enemies[i].size){   

                  player_draw(playerXpos,playerYpos,0x0);win=0;playerExplode=1;vib=1;

            }

            if(enemies[i].status==0)numDeadEnemies++;

            if(enemies[i].y>128)enemies[i].y=1;

        } 

        // check for end game conditions

        if(numDeadEnemies==numEnemies){Thread::wait(1000);break;}

        if(!win){Thread::wait(1000);vib=0;playerExplode=0;break;}

        numDeadEnemies = 0;

        ctr++;

        Thread::wait(10);

    }

    uLCD.locate(5,5);

    if(win){

        uLCD.printf("You Win!!");

    }else{

        uLCD.printf("GAME OVER");

    }

}