A zombie game made for the uLCD
Dependencies: 4DGL-uLCD-SE mbed-rtos mbed
Fork of uLCD144G2_demo by
Diff: main.cpp
- Revision:
- 10:9d16de327719
- Parent:
- 8:31e63caf37e2
- Child:
- 11:4b75ea66467d
diff -r f20983c914aa -r 9d16de327719 main.cpp --- a/main.cpp Wed Oct 28 15:06:56 2015 +0000 +++ b/main.cpp Sun Mar 13 16:00:46 2016 +0000 @@ -1,171 +1,336 @@ -// uLCD-144-G2 demo program for uLCD-4GL LCD driver library -// #include "mbed.h" #include "uLCD_4DGL.h" +#include "Speaker.h" +#include "rtos.h" -uLCD_4DGL uLCD(p9,p10,p11); // serial tx, serial rx, reset pin; - -int main() +//First make the Nav_Switch class for using the joystick +class Nav_Switch { - // basic printf demo = 16 by 18 characters on screen - uLCD.printf("\nHello uLCD World\n"); //Default Green on black text - uLCD.printf("\n Starting Demo..."); - uLCD.text_width(4); //4X size text - uLCD.text_height(4); - uLCD.color(RED); - for (int i=10; i>=0; --i) { - uLCD.locate(1,2); - uLCD.printf("%2D",i); - wait(.5); - } - uLCD.cls(); - uLCD.printf("Change baudrate......"); - uLCD.baudrate(3000000); //jack up baud rate to max for fast display - //if demo hangs here - try lower baud rates - // - // printf text only full screen mode demo - uLCD.background_color(BLUE); - uLCD.cls(); - uLCD.locate(0,0); - uLCD.color(WHITE); - uLCD.textbackground_color(BLUE); - uLCD.set_font(FONT_7X8); - uLCD.text_mode(OPAQUE); - int i=0; - while(i<64) { - if(i%16==0) uLCD.cls(); - uLCD.printf("TxtLine %2D Page %D\n",i%16,i/16 ); - i++; //16 lines with 18 charaters per line - } - wait(0.5); - //demo graphics commands - uLCD.background_color(BLACK); - uLCD.cls(); - uLCD.background_color(DGREY); - uLCD.filled_circle(60, 50, 30, 0xFF00FF); - uLCD.triangle(120, 100, 40, 40, 10, 100, 0x0000FF); - uLCD.line(0, 0, 80, 60, 0xFF0000); - uLCD.filled_rectangle(50, 50, 100, 90, 0x00FF00); - uLCD.pixel(60, 60, BLACK); - uLCD.read_pixel(120, 70); - uLCD.circle(120, 60, 10, BLACK); - uLCD.set_font(FONT_7X8); - uLCD.text_mode(TRANSPARENT); - uLCD.text_bold(ON); - uLCD.text_char('B', 9, 8, BLACK); - uLCD.text_char('I',10, 8, BLACK); - uLCD.text_char('G',11, 8, BLACK); - uLCD.text_italic(ON); - uLCD.text_string("This is a test of string", 1, 4, FONT_7X8, WHITE); - wait(2); +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; -//Bouncing Ball Demo - float fx=50.0,fy=21.0,vx=1.0,vy=0.4; - int x=50,y=21,radius=4; - uLCD.background_color(BLACK); - uLCD.cls(); - //draw walls - uLCD.line(0, 0, 127, 0, WHITE); - uLCD.line(127, 0, 127, 127, WHITE); - uLCD.line(127, 127, 0, 127, WHITE); - uLCD.line(0, 127, 0, 0, WHITE); - for (int i=0; i<1500; i++) { - //draw ball - uLCD.filled_circle(x, y, radius, RED); - //bounce off edge walls and slow down a bit? - if ((x<=radius+1) || (x>=126-radius)) vx = -.90*vx; - if ((y<=radius+1) || (y>=126-radius)) vy = -.90*vy; - //erase old ball location - uLCD.filled_circle(x, y, radius, BLACK); - //move ball - fx=fx+vx; - fy=fy+vy; - x=(int)fx; - y=(int)fy; - } - wait(0.5); -//draw an image pixel by pixel - int pixelcolors[50][50]; - uLCD.background_color(BLACK); - uLCD.cls(); -//compute Mandelbrot set image for display -//image size in pixels - const unsigned ImageHeight=128; - const unsigned ImageWidth=128; - //"c" region to display - double MinRe = -0.75104; - double MaxRe = -0.7408; - double MinIm = 0.10511; - double MaxIm = MinIm+(MaxRe-MinRe)*ImageHeight/ImageWidth; - double Re_factor = (MaxRe-MinRe)/(ImageWidth-1); - double Im_factor = (MaxIm-MinIm)/(ImageHeight-1); - unsigned MaxIterations = 2048; - for(unsigned y=0; y<ImageHeight; ++y) { - double c_im = MaxIm - y*Im_factor; - for(unsigned x=0; x<ImageWidth; ++x) { - double c_re = MinRe + x*Re_factor; - double Z_re = c_re, Z_im = c_im; - int niterations=0; - for(unsigned n=0; n<MaxIterations; ++n) { - double Z_re2 = Z_re*Z_re, Z_im2 = Z_im*Z_im; - if(Z_re2 + Z_im2 > 4) { - niterations = n; - break; - } - Z_im = 2*Z_re*Z_im + c_im; - Z_re = Z_re2 - Z_im2 + c_re; - } - if (niterations!=(MaxIterations-1)) - uLCD.pixel(x,y,((niterations & 0xF00)<<12)+((niterations & 0xF0)<<8)+((niterations & 0x0F)<<4) ); +}; +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); } - } - wait(5); -// PLASMA wave BLIT animation -//draw an image using BLIT (Block Image Transfer) fastest way to transfer pixel data - uLCD.cls(); - int num_cols=50; - int num_rows=50; - int frame=0; - double a,b,c=0.0; - while(frame<75) { - for (int k=0; k<num_cols; k++) { - b= (1+sin(3.14159*k*0.75/(num_cols-1.0)+c))*0.5; - for (int i=0; i<num_rows; i++) { - a= (1+sin(3.14159*i*0.75/(num_rows-1.0)+c))*0.5; - // a and b will be a sine wave output between 0 and 1 - // sine wave was scaled for nice effect across array - // uses a and b to compute pixel colors based on rol and col location in array - // also keeps colors at the same brightness level - if ((a+b) <.667) - pixelcolors[i][k] = (255-(int(254.0*((a+b)/0.667)))<<16) | (int(254.0*((a+b)/0.667))<<8) | 0; - else if ((a+b)<1.333) - pixelcolors[i][k] = (0 <<16) | (255-(int (254.0*((a+b-0.667)/0.667)))<<8) | int(254.0*((a+b-0.667)/0.667)); - else - pixelcolors[i][k] = (int(255*((a+b-1.333)/0.667))<<16) | (0<<8) | (255-(int (254.0*((a+b-1.333)/0.667)))); - } + 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); } - uLCD.BLIT(39, 39, 50, 50, &pixelcolors[0][0]); - c = c + 0.0314159*3.0; - if (c > 6.2831) c = 0.0; - frame++; - } - //Load Image Demo - uLCD.cls(); - //SD card needed with image and video files for last two demos - uLCD.cls(); - uLCD.media_init(); - uLCD.printf("\n\nAn SD card is needed for image and video data"); - uLCD.set_sector_address(0x001D, 0x4C01); - uLCD.display_image(0,0); - wait(10); - //Play video demo - while(1) { - uLCD.cls(); - uLCD.media_init(); - uLCD.set_sector_address(0x001D, 0x4C42); - uLCD.display_video(0,0); } } +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+j) { + 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; + } + } + } + +} + + +