WITB2

Dependencies:   mbed 4DGL-uLCD-SE PinDetect

main.cpp

Committer:
Nydrel
Date:
2018-11-29
Revision:
5:ed52ac77cdf9
Parent:
4:d128df681d05

File content as of revision 5:ed52ac77cdf9:

#include "mbed.h"
#include "MMA8452.h"
#include "uLCD_4DGL.h"
#include "PinDetect.h"
#include "Speaker.h"
#include <ctime>

/*-----Define Statements-----*/

#define ASTEROID_HEIGHT 12
#define ASTEROID_WIDTH 15
#define SPRITE_MAX 15
#define EARTH_WIDTH 10
#define EARTH_HEIGHT 10
#define EXPLOSION1_WIDTH 20
#define SCREEN_MAX 125
#define SCREEN_MIN 1
#define NUM_ASTEROIDS 4
#define Q 0x808000 //OLIVE
#define I 0x008000 //GREEN
#define S 0xC0C0C0 //SILVER
#define C 0x17202A //UFO GLASS
#define D 0x797D7F //DARK GREY
#define L 0x00FF00 //LIME
#define P 0xFF00FF //PINK
#define R 0xF1C40F //YELLOW
#define O 0xF39C12 //ORANGE
#define G 0xAAB7B8 //GREY
#define _ 0x000000 //BLACK
#define X 0xFFFFFF //WHITE
#define B 0x0000FF //BLUE
#define r 0xFF0000 //RED


/*-----Sprites------*/

int spaceship_earth1[EARTH_WIDTH * EARTH_HEIGHT] = 
{
    _,_,S,S,S,S,S,S,_,_,
    _,S,I,I,I,I,I,I,S,_,
    S,I,I,I,I,I,I,I,I,S,
    S,I,I,I,I,I,I,I,I,S,
    S,I,I,I,I,I,I,I,I,S,
    S,I,I,I,I,I,I,I,I,S,
    S,I,I,I,I,I,I,I,I,S,
    S,I,I,I,I,I,I,I,I,S,
    S,I,I,I,I,I,I,I,S,_,
    _,S,S,S,S,S,S,S,_,_
};

int earth_blank[EARTH_WIDTH * EARTH_HEIGHT] = 
{
    _,_,_,_,_,_,_,_,_,_,
    _,_,_,_,_,_,_,_,_,_,
    _,_,_,_,_,_,_,_,_,_,
    _,_,_,_,_,_,_,_,_,_,
    _,_,_,_,_,_,_,_,_,_,
    _,_,_,_,_,_,_,_,_,_,
    _,_,_,_,_,_,_,_,_,_,
    _,_,_,_,_,_,_,_,_,_,
    _,_,_,_,_,_,_,_,_,_,
    _,_,_,_,_,_,_,_,_,_
};


int earth_destroy[EARTH_WIDTH * EARTH_HEIGHT] = 
{
    R,R,R,R,R,R,R,R,R,R,
    R,R,r,_,_,r,_,_,r,R,
    R,R,_,r,_,r,_,r,_,R,
    R,R,_,_,r,r,r,_,_,R,
    R,R,r,r,r,r,r,r,r,R,
    R,R,_,_,r,r,r,_,_,R,
    R,R,_,r,_,r,_,r,_,R,
    R,R,r,_,_,r,_,_,r,R,
    R,R,R,R,R,R,R,R,R,R,
    R,R,R,R,R,R,R,R,R,R
};

int asteroid_sprite_1[ASTEROID_HEIGHT * ASTEROID_WIDTH] = {
_,_,_,_,X,X,X,X,X,X,X,X,_,_,_,
_,_,_,X,_,_,_,_,_,_,_,_,X,_,_,
_,_,X,_,_,_,_,_,_,_,_,_,X,_,_,
_,X,_,_,_,_,_,_,_,_,_,_,X,_,_,
X,X,X,X,_,_,_,_,_,_,_,_,_,X,_,
_,_,_,X,_,_,_,_,_,_,_,_,_,X,_,
_,_,X,_,_,_,_,_,_,_,_,_,_,X,_,
_,X,_,_,_,_,_,X,_,_,_,_,_,X,_,
X,_,_,_,_,_,X,X,_,_,_,_,X,_,_,
_,X,_,_,_,X,_,X,_,_,_,_,X,_,_,
_,_,X,_,X,_,_,X,_,_,_,X,_,_,_,
_,_,_,X,_,_,_,X,X,X,X,_,_,_,_
};


int asteroid_sprite_2[ASTEROID_HEIGHT * ASTEROID_WIDTH] = {
_,_,X,X,X,X,X,X,X,X,_,_,_,_,_,
_,_,_,X,_,_,_,_,_,_,X,X,_,_,_,
_,_,_,_,X,_,_,_,_,_,_,_,X,_,_,
X,X,X,X,X,X,_,_,_,_,_,_,_,X,_,
X,_,_,_,_,_,_,_,_,_,_,_,_,_,X,
X,_,_,_,_,_,_,_,_,_,_,_,_,X,X,
X,_,_,_,_,_,_,_,_,_,_,X,X,_,_,
_,X,_,_,_,_,_,_,_,_,X,_,_,_,_,
_,_,X,_,_,_,_,_,_,_,_,X,X,_,_,
_,_,_,X,_,_,_,_,X,_,_,_,_,X,X,
_,_,_,_,X,_,X,X,_,X,X,_,_,X,_,
_,_,_,_,_,X,_,_,_,_,_,X,X,_,_
};


int asteroid_sprite_3[ASTEROID_HEIGHT * ASTEROID_WIDTH] = {
_,_,X,X,X,_,_,_,_,_,_,X,X,_,_,
_,X,_,_,_,X,X,_,_,_,X,_,_,X,_,
X,_,_,_,_,_,_,X,X,X,_,_,_,_,X,
_,X,_,_,_,_,_,_,_,_,_,_,_,X,_,
_,_,X,_,_,_,_,_,_,_,X,X,X,_,_,
_,_,_,X,_,_,_,_,_,_,X,X,_,_,_,
_,_,X,_,_,_,_,_,_,_,_,_,X,_,_,
_,X,_,_,_,_,_,_,_,_,_,_,_,X,_,
X,_,_,_,_,_,_,_,_,_,_,_,_,_,X,
_,X,_,_,_,X,X,X,_,_,_,_,_,X,_,
_,_,X,_,X,_,_,_,X,X,_,X,X,_,_,
_,_,_,X,_,_,_,_,_,_,X,X,X,_,_
};


int asteroid_sprite_4[ASTEROID_HEIGHT * ASTEROID_WIDTH] = {
_,_,_,X,X,_,_,_,_,_,X,_,_,_,_,
_,_,X,_,_,X,_,_,_,X,_,X,X,_,_,
_,X,_,_,_,_,X,_,X,_,_,_,_,X,_,
X,_,_,_,_,_,_,X,_,_,_,_,_,_,X,
X,_,_,_,_,_,_,_,_,_,_,_,_,X,_,
X,_,_,_,_,_,_,_,_,_,_,_,X,_,_,
X,_,_,_,_,_,_,_,_,_,_,_,_,X,_,
X,_,_,_,_,_,_,_,_,_,_,_,_,_,X,
X,_,_,_,_,_,_,_,_,_,_,_,_,X,_,
_,X,_,_,_,_,_,_,_,_,_,_,X,_,_,
_,_,X,_,_,_,_,_,_,_,_,X,_,_,_,
_,_,_,X,X,X,X,X,X,X,X,_,_,_,_
};


int asteroid_blank[ASTEROID_WIDTH * ASTEROID_HEIGHT] = 
{
_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,
_,_,_,_,_,_,_,_,_,_,_,_,_,_,_
};



//Instantiate Accelerometer Object

Serial pc(USBTX,USBRX); //not used in this program
MMA8452 acc(p9, p10, 40000);  //instantiate an acc object!
double x, y, z;

//Instantiate uLCD Object

DigitalOut myled(LED1);
uLCD_4DGL uLCD(p28, p27, p29); // create a global uLCD object
Speaker mySpeaker(p21);

//Setup pushbutton for bomb
PinDetect pb1(p16);

int factor = 50;
int offset = 63;
bool BombUsed = false;
bool ExplodeAllAsteroids = false;


void pb1_hit_callback (void)
{
    if (!BombUsed )
    {
        ExplodeAllAsteroids = true;
        BombUsed = true;
    }
}

/*-----ScreenObject Class------*/

class ScreenObject
{
public:
    //ScreenObject();
    //setter functions
    
    /*void setXPos(int x)
    {
        x_pos = x;
    }
    
    void setYPos(int y)
    {
        y_pos = y;
    } */

    //getter functions
//    int getXPos();
  //  int getYPos();

    //pure virtual
    virtual void draw() = 0;
    virtual void update() = 0;
    virtual bool boundaryCheck() = 0;
    virtual void reset() = 0;
    
    friend bool overlap(ScreenObject & objectA, ScreenObject & objectB)
    {
        bool rangeX = (objectA.x_pos <= objectB.x_pos + 7) && (objectA.x_pos + 8 >= objectB.x_pos);
        bool rangeY = (objectA.y_pos <= objectB.y_pos + 7) && (objectA.y_pos + 7 >= objectB.y_pos);
        return (rangeX && rangeY);
    }
//you put stuff in here!

protected:
    int x_pos;
    int y_pos;
};


/*-----SpaceShipEarth Class------*/

class SpaceShipEarth: public ScreenObject
{
public:
    SpaceShipEarth() {
        x_pos = 63;
        y_pos = 63;
    }

    void draw() {
        uLCD.BLIT(x_pos, y_pos, EARTH_WIDTH, EARTH_HEIGHT,spaceship_earth1);
    }

    void update() {
        
        uLCD.BLIT(x_pos, y_pos, EARTH_WIDTH, EARTH_HEIGHT,earth_blank);
        
        if(!acc.isXYZReady()) {
            wait(0.02);
        }

        else {
            acc.readXYZGravity(&x,&y,&z); //notice this is passed by reference use pointers
            x_pos = -1*x*factor + offset;
            y_pos = -1*y*factor + offset;

        } //end else
    }//end if
    
    void explode() {
        uLCD.BLIT(x_pos, y_pos, EARTH_WIDTH, EARTH_HEIGHT,earth_blank);
        uLCD.BLIT(x_pos, y_pos, EARTH_WIDTH, EARTH_HEIGHT,earth_destroy);
    }
    
    bool boundaryCheck()
    {
        if(((x_pos == 0) || (x_pos == 126)) || ((y_pos == 0) || (y_pos == 126)))
            return true;
        else
            return false;
    }
    
    void reset()
    {
     x_pos = 63;
     y_pos = 63; 
    }
    
    /*
    bool boundaryCheck(* ScreenObject asteroid)
    {
        //compare the four corners of the Earth and asteroid sprites
        bool c1 = (asteroid->x_pos) <=
    }
    */

};



/*-----AbstractAsteroid Class-----*/


class AbstractAsteroid: public ScreenObject
{
public: 
    void pickCorner(int corner)
    {   
        switch (corner)
        {
            case 1:     //top left
                x_pos = 2;
                y_pos = 2;
                deltaX = rand() % 3 + 1; 
                deltaY = rand() % 3 + 1;
                break;
            case 2:     //top right
                x_pos = 124 - ASTEROID_WIDTH;
                y_pos = 2;
                deltaX = -1*(rand() % 3 + 1); 
                deltaY = rand() % 3 + 1;
                break;
            case 3:     //bottom left
                x_pos = 2;
                y_pos = 124 - ASTEROID_HEIGHT;
                deltaX = rand() % 3 + 1; 
                deltaY = -1*(rand() % 3 + 1);
                break;
            case 4:     //bottom right
                x_pos = 124 - ASTEROID_WIDTH;
                y_pos = 124 - ASTEROID_HEIGHT;
                deltaX = -1*(rand() % 3 + 1); 
                deltaY = -1*(rand() % 3 + 1);
                break;
        }
    }
    
    void pickEdge()
    {   
        int edge = rand() % 4 + 1;
    
        switch (edge)
        {
            case 1:     //top
                x_pos = rand() % 2 + (120 - ASTEROID_WIDTH);
                y_pos = 2;
                if((rand() % 1))
                    deltaX = rand() % 3 + 1;
                else  
                    deltaX = -1*(rand() % 3 + 1);
                deltaY = rand() % 3 + 1;
                break;
            case 2:     //bottom
                x_pos = rand() % 2 + (120 - ASTEROID_WIDTH);
                y_pos = 120 - ASTEROID_HEIGHT;
                if((rand() % 1))
                    deltaX = rand() % 3 + 1;
                else  
                    deltaX = -1*(rand() % 3 + 1); 
                deltaY = -1*(rand() % 3 + 1);
                break;
            case 3:     //left
                x_pos = 2;
                y_pos = rand() % 1 + (120 - ASTEROID_HEIGHT);
                deltaX = rand() % 3 + 1; 
                if((rand() % 1))
                    deltaY = rand() % 3 + 1;
                else  
                    deltaY = -1*(rand() % 3 + 1);
                break;
            case 4:     //right
                x_pos = 120 - ASTEROID_WIDTH;
                y_pos = rand() % 1 + (120 - ASTEROID_HEIGHT);
                deltaX = -1*(rand() % 3 + 1); 
                if((rand() % 1))
                    deltaY = rand() % 3 + 1;
                else  
                    deltaY = -1*(rand() % 3 + 1);
                break;
        }
    } 
    
    
    bool boundaryCheck()
    {
        bool c1 = x_pos + ASTEROID_WIDTH > 124; //if moving towards right side of screen
        bool c2 = x_pos <= 0; //if moving towards left side of screen
        bool c3 = y_pos + ASTEROID_HEIGHT > 124; //if moving towards bottom of screen
        bool c4 = y_pos <= 0; //if moving towards top of screen
        
        if(c1 || c2 || c3 || c4)
            return true;
        else
            return false;
    }
    
protected:    
    int deltaX;
    int deltaY; 
};



//-----Concrete Asteroids-----//

//-----Asteroid1-----//
class Asteroid1: public AbstractAsteroid
{
public: 
    Asteroid1(int corner)
    {
       pickCorner(corner);
       startTime = time(0); 
    }
    
    void reset()
    {
        pickEdge();
        startTime = time(0);
    }
    
    void draw()
    { 
        uLCD.BLIT(x_pos, y_pos, ASTEROID_WIDTH, ASTEROID_HEIGHT,asteroid_sprite_1);
    }   
    
    void update()
    {
        uLCD.BLIT(x_pos, y_pos, ASTEROID_WIDTH, ASTEROID_HEIGHT,asteroid_blank);
        wait(0.02);
        time_t timeElapsed = time(0)-startTime;
        x_pos = x_pos + (deltaX * timeElapsed);
        y_pos = y_pos + (deltaY * timeElapsed);
    }
    
    
protected:
     time_t startTime;
};


//-----Asteroid2-----//
class Asteroid2: public AbstractAsteroid
{
public: 
    Asteroid2(int corner)
    {
       pickCorner(corner);
       startTime = time(0); 
    }
    
    void reset()
    {
        pickEdge();
        startTime = time(0);
    }
    
    void draw()
    {
        uLCD.BLIT(x_pos, y_pos, ASTEROID_WIDTH, ASTEROID_HEIGHT,asteroid_sprite_2);
    }   
    
    void update()
    {
        uLCD.BLIT(x_pos, y_pos, ASTEROID_WIDTH, ASTEROID_HEIGHT,asteroid_blank);
        wait(0.02);
        time_t timeElapsed = time(0)-startTime;
        x_pos = x_pos + (deltaX * timeElapsed);
        y_pos = y_pos + (deltaY * timeElapsed);
    }
    
protected:
     time_t startTime;
};




//-----Asteroid3-----//
class Asteroid3: public AbstractAsteroid
{
public: 
    Asteroid3(int corner)
    {
       pickCorner(corner);
       startTime = time(0); 
    }
    
    void reset()
    {
        pickEdge();
        startTime = time(0);
    }
    
    void draw()
    {
        uLCD.BLIT(x_pos, y_pos, ASTEROID_WIDTH, ASTEROID_HEIGHT,asteroid_sprite_3);
    }   
    
    void update()
    {
        uLCD.BLIT(x_pos, y_pos, ASTEROID_WIDTH, ASTEROID_HEIGHT,asteroid_blank);
        wait(0.02);
        time_t timeElapsed = time(0)-startTime;
        x_pos = x_pos + (deltaX * timeElapsed);
        y_pos = y_pos + (deltaY * timeElapsed);
    }
    
    
protected:
     time_t startTime;
};



//-----Asteroid4-----//
class Asteroid4: public AbstractAsteroid
{
public: 
    Asteroid4(int corner)
    {
       pickCorner(corner);
       startTime = time(0); 
    }
    
    void reset()
    {
        pickEdge();
        startTime = time(0);
    }
    
    void draw()
    {
        uLCD.BLIT(x_pos, y_pos, ASTEROID_WIDTH, ASTEROID_HEIGHT,asteroid_sprite_4);
    }   
    
    void update()
    {
        uLCD.BLIT(x_pos, y_pos, ASTEROID_WIDTH, ASTEROID_HEIGHT,asteroid_blank);
        wait(0.02);
        time_t timeElapsed = time(0)-startTime;
        x_pos = x_pos + (deltaX * timeElapsed);
        y_pos = y_pos + (deltaY * timeElapsed);
    }
    
    
protected:
     time_t startTime;
};




//Program Start

int main()
{
    uLCD.baudrate(300000);
    wait(0.2);
    srand(time(0)); // do this srand call here ONLY... no where else in the code!
    ScreenObject * ActiveAsteroids[NUM_ASTEROIDS];
    SpaceShipEarth ship; //instantiate a SpaceShipEarth object
    
    pb1.mode(PullUp);
    wait(0.01);
    pb1.attach_deasserted(&pb1_hit_callback);
    pb1.setSampleFrequency();
   
    
    double bar = 127;
   
    Asteroid1 rock1(1);
    Asteroid2 rock2(2);
    Asteroid3 rock3(3);
    Asteroid4 rock4(4);
   
    ActiveAsteroids[0] = &rock1;
    ActiveAsteroids[1] = &rock2;
    ActiveAsteroids[2] = &rock3;
    ActiveAsteroids[3] = &rock4;

//set parameters -- use these and don't change
    acc.setBitDepth(MMA8452::BIT_DEPTH_12);
    acc.setDynamicRange(MMA8452::DYNAMIC_RANGE_4G);
    acc.setDataRate(MMA8452::RATE_100);
    
    
    time_t startTime;
    time_t timeElapsed;
    startTime = time(0);
    
    int dur = 30;

    while(1) {
        //check winning condition
        if((time(0)-startTime) > dur)
        {
            uLCD.printf("YOU WIN!");
            return 1;
        }
        
        else
        {
            timeElapsed = time(0)-startTime;
            bar = 127 - (timeElapsed*(127/dur));
            uLCD.filled_rectangle(1, 1,127,1,R);
            uLCD.filled_rectangle(1, 1,127-bar,1,_);
        }
                
        ship.update();

        ship.draw();
        
        
        ActiveAsteroids[0]->update();
        
        if(ActiveAsteroids[0]->boundaryCheck())
            ActiveAsteroids[0]->reset();
        
        ActiveAsteroids[0]->draw();
        
        ActiveAsteroids[1]->update();
        
        if(ActiveAsteroids[1]->boundaryCheck())
            ActiveAsteroids[1]->reset();
        
        ActiveAsteroids[1]->draw();
    
        ActiveAsteroids[2]->update();
        
        if(ActiveAsteroids[2]->boundaryCheck())
            ActiveAsteroids[2]->reset();
        
        ActiveAsteroids[2]->draw();
          
        ActiveAsteroids[3]->update(); 
        
        if(ActiveAsteroids[3]->boundaryCheck())
            ActiveAsteroids[3]->reset();
        
        ActiveAsteroids[3]->draw();
        
        
        //check to see if the pushbutton has activated the bomb
        if(ExplodeAllAsteroids)
        {
            for(int i = 0; i < 4; i++)
                {
                    ActiveAsteroids[i]->update();
                    wait(0.25);
                    ActiveAsteroids[i]->reset();
                }
            ExplodeAllAsteroids = false;
        }
        
        
        //check for overlap between Asteroids and Earth
        //return 1 and end game
        if(overlap(ship,rock1)) {
            ship.explode();
            mySpeaker.PlayNote(500.0,0.25,0.1);
            mySpeaker.PlayNote(450.0,0.25,0.1);
            mySpeaker.PlayNote(400.0,0.25,0.1);
            mySpeaker.PlayNote(300.0,0.25,0.1);
            uLCD.printf("GAME OVER");
            wait(3);
            return 1;
        }
        
        else if(overlap(ship,rock2)) {
            ship.explode();
            mySpeaker.PlayNote(500.0,0.25,0.1);
            mySpeaker.PlayNote(450.0,0.25,0.1);
            mySpeaker.PlayNote(400.0,0.25,0.1);
            mySpeaker.PlayNote(300.0,0.25,0.1);
            uLCD.printf("GAME OVER");
            wait(3);
            return 1;
        }
        
        else if(overlap(ship,rock3)) {
            ship.explode();
            mySpeaker.PlayNote(500.0,0.25,0.1);
            mySpeaker.PlayNote(450.0,0.25,0.1);
            mySpeaker.PlayNote(400.0,0.25,0.1);
            mySpeaker.PlayNote(300.0,0.25,0.1);
            uLCD.printf("GAME OVER");
            wait(3);
            return 1;
        }
        
        else if(overlap(ship,rock4)) {
            ship.explode();
            mySpeaker.PlayNote(500.0,0.25,0.1);
            mySpeaker.PlayNote(450.0,0.25,0.1);
            mySpeaker.PlayNote(400.0,0.25,0.1);
            mySpeaker.PlayNote(300.0,0.25,0.1);
            uLCD.printf("GAME OVER");
            wait(3);
            return 1;
        }
        
        
        //check to see if the game is over
    
    } //end infinite while loop
} //end main