A zombie game made for the uLCD

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

Fork of uLCD144G2_demo by jim hamblen

main.cpp

Committer:
rjones75
Date:
2016-03-14
Revision:
11:4b75ea66467d
Parent:
10:9d16de327719

File content as of revision 11:4b75ea66467d:

#include "mbed.h"
#include "uLCD_4DGL.h"
#include "Speaker.h"
#include "rtos.h"

//First make the Nav_Switch class for using the joystick
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();
}

//Now initialize
uLCD_4DGL uLCD(p28,p27,p30); // serial tx, serial rx, reset pin;
Nav_Switch myNav(p11,p14,p13,p15,p12);
Speaker mySpeaker(p21);

//Game states: Start screen, playing, and game over
enum gamestate {
    start,
    playing,
    gameover
};

//Which way you're facing is where you fire your gun
enum facingDirection {
    up,
    down,
    left,
    right
};

//Global variables used by SpeakerThread
//The game state
int state=start;
//Checks for each bullet (up,down,left,right) to see if it hit an enemy
bool hitU=false, hitD=false, hitL=false, hitR=false;

void SpeakerThread(void const *args)
{
    while(1) {
        if(myNav.fire() && state==playing) {
            //Play noise when gun is fired
            mySpeaker.PlayNote(500.0,0.1,0.5);
        }
        if(hitU || hitD || hitL || hitR) {
            //Play two notes when enemy hit.
            mySpeaker.PlayNote(300.0,0.05,0.5);
            mySpeaker.PlayNote(250.0,0.05,0.5);
        }
    }
}



int main()
{
    while(1) {
        //Score
        int score=0;
        //Player position (initialized at center).
        int Px1=63-1,Px2=63+1,Py1=63-1,Py2=63+1;
        //X and Y coordinates for each bullet
        int BUx=0, BUy=0, BLx=0, BLy=0;
        int BDx=127, BDy=127, BRx=127, BRy=127;
        //Zombie coordinates. Z[0][0] = x coordinate of zombie 1, Z[0][1] = y coordinate of zombie 1.
        //Z[0][0] = x1 coordinate, Z[0][0]+2 = x2 coordinate. Same method for y1 and y2.
        int Z[1][2];
        for(int i=0; i<2; i++) {
            for(int j=0; j<2; j++) {
                Z[i][j]=0;
            }
        }
        //Which way the player is facing
        int facing=down;
        //Threads
        Thread speaker(SpeakerThread);
        //Display the start screen
        uLCD.media_init();
        uLCD.set_sector_address(0x001D, 0x4C01);
        uLCD.display_image(0,0);
        //Switch to the playing state when FIRE is pressed
        while(state==start) {
            if(myNav.fire()) {
                uLCD.cls();
                wait(1.0);
                state=playing;
            }
        }

        //Draw player and zombie
        uLCD.filled_rectangle(Px1,Py1,Px2,Py2,BLUE);
        uLCD.filled_rectangle(Z[0][0],Z[0][1],Z[0][0]+2,Z[0][1]+2,GREEN);

        //Game starts here
        while(state==playing) {

            //Player Movement
            //Move the player when buttons are pressed (but don't go off the screen)
            if(myNav.up() && (Py1!=0)) {
                facing=up;
                Py1--;
                Py2--;
                uLCD.filled_rectangle(Px1,Py1,Px2,Py2,BLUE);
                uLCD.filled_rectangle(Px1,Py2+1,Px2,Py2+1,BLACK);
            } else if(myNav.down() && (Py2!=127)) {
                facing=down;
                Py1++;
                Py2++;
                uLCD.filled_rectangle(Px1,Py1,Px2,Py2,BLUE);
                uLCD.filled_rectangle(Px1,Py1-1,Px2,Py1-1,BLACK);
            } else if(myNav.left() && (Px1!=0)) {
                facing=left;
                Px1--;
                Px2--;
                uLCD.filled_rectangle(Px1,Py1,Px2,Py2,BLUE);
                uLCD.filled_rectangle(Px2+1,Py1,Px2+1,Py2,BLACK);
            } else if(myNav.right() && (Px2!=127)) {
                facing=right;
                Px1++;
                Px2++;
                uLCD.filled_rectangle(Px1,Py1,Px2,Py2,BLUE);
                uLCD.filled_rectangle(Px1-1,Py1,Px1-1,Py2,BLACK);
            }
            //Firing the gun depending on where you are facing
            if(myNav.fire() && facing==up && BUy==0) {
                BUx=Px1+1;
                BUy=Py1-1;
                uLCD.pixel(BUx,BUy,WHITE);
            } else if(myNav.fire() && facing==down && BDy==127) {
                BDx=Px1+1;
                BDy=Py2+1;
                uLCD.pixel(BDx,BDy,WHITE);
            } else if(myNav.fire() && facing==left  && BLx==0) {
                BLx=Px1-1;
                BLy=Py2-1;
                uLCD.pixel(BLx,BLy,WHITE);
            } else if(myNav.fire() && facing==right && BRx==127) {
                BRx=Px2+1;
                BRy=Py2-1;
                uLCD.pixel(BRx,BRy,WHITE);
            }
            //Keep moving the bullets until they hit the wall or a zombie
            if(BUy!=0 && !hitU) {
                BUy--;
                uLCD.pixel(BUx,BUy,WHITE);
                uLCD.pixel(BUx,BUy+1,BLACK);
                //Hit detection
                for(int i=0; i<3; i++) {
                    for(int j=0; j<3; j++) {
                        if((Z[0][0]+i)==BUx && (Z[0][1]+j)==BUy) {
                            hitU=true;
                        }
                    }
                }
            } else  {
                uLCD.filled_rectangle(BUx-2,BUy-2,BUx+2,BUy+1,BLACK);
                BUy=0;
                hitU=false;
            }
            if(BDy!=127 && !hitD) {
                BDy++;
                uLCD.pixel(BDx,BDy,WHITE);
                uLCD.pixel(BDx,BDy-1,BLACK);
                //Hit detection
                for(int i=0; i<3; i++) {
                    for(int j=0; j<3; j++) {
                        if((Z[0][0]+i)==BDx && (Z[0][1]+j)==BDy) {
                            hitD=true;
                        }
                    }
                }
            } else  {
                uLCD.filled_rectangle(BDx-2,BDy-1,BDx+2,BDy+2,BLACK);
                BDy=127;
                hitD=false;
            }
            if(BLx!=0 && !hitL) {
                BLx--;
                uLCD.pixel(BLx,BLy,WHITE);
                uLCD.pixel(BLx+1,BLy,BLACK);
                //Hit detection
                for(int i=0; i<3; i++) {
                    for(int j=0; j<3; j++) {
                        if((Z[0][0]+i)==BLx && (Z[0][1]+j)==BLy) {
                            hitL=true;
                        }
                    }
                }
            } else {
                uLCD.filled_rectangle(BLx-2,BLy-2,BLx+1,BLy+2,BLACK);
                BLx=0;
                hitL=false;
            }
            if(BRx!=127 && !hitR) {
                BRx++;
                uLCD.pixel(BRx,BRy,WHITE);
                uLCD.pixel(BRx-1,BRy,BLACK);
                //Hit detection
                for(int i=0; i<3; i++) {
                    for(int j=0; j<3; j++) {
                        if((Z[0][0]+i)==BRx && (Z[0][1]+j)==BRy) {
                            hitR=true;
                        }
                    }
                }
            } else {
                uLCD.filled_rectangle(BRx-1,BRy-2,BRx+2,BRy+2,BLACK);
                BRx=127;
                hitR=false;
            }


            //Zombie Movement
            if(!hitU && !hitD && !hitL && !hitR) {
                if(Px1 > (Z[0][0]+2)) {
                    Z[0][0]=Z[0][0]+1;
                    uLCD.filled_rectangle(Z[0][0]-1,Z[0][1],Z[0][0]-1,Z[0][1]+2,BLACK);
                } else if(Px2 < Z[0][0]) {
                    Z[0][0]--;
                    uLCD.filled_rectangle(Z[0][0]+3,Z[0][1],Z[0][0]+3,Z[0][1]+2,BLACK);
                }
                if(Py1 > Z[0][1]+2) {
                    Z[0][1]++;
                    uLCD.filled_rectangle(Z[0][0],Z[0][1]-1,Z[0][0]+2,Z[0][1]-1,BLACK);
                } else if(Py2 < Z[0][1]) {
                    Z[0][1]--;
                    uLCD.filled_rectangle(Z[0][0],Z[0][1]+3,Z[0][0]+2,Z[0][1]+3,BLACK);
                }
                uLCD.filled_rectangle(Z[0][0],Z[0][1],Z[0][0]+2,Z[0][1]+2,GREEN);
            }
            //If zombie is hit, add 10 points and move the zombie to a random spot outside of the
            //map that doesn't hit (0,0) or (127,127), which is where the bullets are held
            if(hitU || hitD || hitL || hitR) {
                score += 10;
                if(rand() % 2) {
                    Z[0][0] = (rand() % 120)+1;
                    if(rand() % 2)
                        Z[0][1] = -3;
                    else
                        Z[0][1] = 128;
                } else {
                    Z[0][1] = (rand() % 120)+1;
                    if(rand() % 2)
                        Z[0][0] = -3;
                    else
                        Z[0][0] = 128;
                }
            }
            //Check if zombie touches player, resulting in game over
            for(int i=0; i<3; i++) {
                for(int j=0; j<3; j++) {
                    if((Z[0][0]+i)==Px1+j) {
                        for(int m=0; m<3; m++) {
                            for(int n=0; n<3; n++) {
                                if((Z[0][1]+m)==Py1+n) {
                                    state=gameover;
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            //Display score in the top
            uLCD.locate(6,0);
            uLCD.printf("Score: %d",score);
        }
        //Display Game Over Screen
        uLCD.media_init();
        uLCD.set_sector_address(0x001D, 0x4C65);
        uLCD.display_image(0,0);
        //Reset when FIRE is pressed
        while(state==gameover) {
            if(myNav.fire()) {
                uLCD.cls();
                wait(1.0);
                state=start;
            }
        }
    }

}