A skydiving game created using an mbed. This code used threads and mutexes to create a skydiving simulation on an uLCD. The sounds being played are read off of a microSD card and played through the speakers. The user controls the skydiver's movements with a navigation switch.
Dependencies: 4DGL-uLCD-SE SDFileSystem mbed-rtos mbed wave_player
Revision 0:2bc06deb0e7d, committed 2016-03-16
- Comitter:
- mhennessy3
- Date:
- Wed Mar 16 20:13:23 2016 +0000
- Child:
- 1:d0bc93562029
- Commit message:
- publish skydiving game 1
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/4DGL-uLCD-SE.lib Wed Mar 16 20:13:23 2016 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/4180_1/code/4DGL-uLCD-SE/#2cb1845d7681
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SDFileSystem.lib Wed Mar 16 20:13:23 2016 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/SDFileSystem/#c8f66dc765d4
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Wed Mar 16 20:13:23 2016 +0000 @@ -0,0 +1,417 @@ +#include "mbed.h" +#include "rtos.h" +#include "uLCD_4DGL.h" +#include "SDFileSystem.h" +#include "wave_player.h" + +uLCD_4DGL uLCD(p28,p27,p30); // serial tx, serial rx, reset pin; +Mutex lcd_mutex;// Create the mutex lock object +PwmOut speaker(p21); //create a PwmOut object for the speaker +SDFileSystem sd(p5, p6, p7, p21, "sd"); //SD card +AnalogOut DACout(p18); +wave_player waver(&DACout); + +///////////////////////////////////////////////////////////////////////////////////////////// +//Navigation Switch class +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(); +} + +Nav_Switch myNav( p12, p9, p10, p8, p11); //pin order on Sparkfun breakout + + +////////////////////////////////////////////////////////////////////////////////////////////// + +// initialize variables + +int rx1, ry1, rrx1, rry1, rrrx1, rrry1, length; +int rx2, rrx2, rrrx2; +int dis_top, midC, breakT; +int tx1, ty1, lx1, ly1; +int stopLength, circY, parachute; +int shapeColor1, count; +// thread to write to LCD screen +void thread1(void const *args){ + //generates obstacles + + while(true){ + + lcd_mutex.lock();//acquire lock + + //Erase previous position of obstacles + uLCD.filled_rectangle(rx1, ry1, rx1+10, ry1+10, BLUE); + uLCD.filled_rectangle(rrx1, rry1, rrx1+10, rry1+10, BLUE); + uLCD.filled_rectangle(rrrx1, rrry1, rrrx1+10, rrry1+10, BLUE); + + if(length<stopLength) { + //continues the loop from offscreen to back on the screen when within a looped time + if(ry1<0){ + ry1=137; + rx1=(rx1+30)%127; + shapeColor1 = (shapeColor1 + 0x110000) & 0xFFFFFF; + } + if(rry1<0){ + rry1=137; + rrx1=(rrx1+65)%127; + } + if(rrry1<0){ + rrry1=137; + rrrx1=(rrrx1+93)%127; + } + if(ly1<0){ + ly1=137; + lx1 = (lx1+50)%127; + } + } + // update positions of obstacles + ry1 = ry1-10; + rry1 = rry1-10; + rrry1 = rrry1-10; + + ty1 = ty1-10; + ly1 = ly1-10; + + wait(.01); + // draw updated obstacles + uLCD.filled_rectangle(rx1, ry1, rx1+10, ry1+10,shapeColor1);//change position + uLCD.filled_rectangle(rrx1, rry1, rrx1+10, rry1+10,0xFF3300);//change position + uLCD.filled_rectangle(rrrx1, rrry1, rrrx1+10, rrry1+10,0x99ffcc);//change position + lcd_mutex.unlock();//release lock + + + //Checking for collisions with obstacles + rx2 = rx1+10; + rrx2 = rrx1+10; + rrrx2 = rrrx1 +10; + dis_top= 8+7; //y pos of circle +radius 7 + // detect a collision between skydiver and obstacle + + //circle 1 + if( (((midC-7)<=rx2 && rx2<=(midC+7)) || ((midC-7)<=rx1 && rx1<=(midC+7))) && ((ry1<dis_top) && (ry1>0))) { + lcd_mutex.lock(); + uLCD.cls(); + uLCD.text_width(2); //2X size text + uLCD.text_height(2); + uLCD.color(RED); + uLCD.locate(2,2); + uLCD.printf("\n GAME \n OVER!\n"); + wait(.05); + lcd_mutex.unlock(); + break; + } + + //circle 2 + if( (((midC-7)<=rrx2 && rrx2<=(midC+7)) || ((midC-7)<=rrx1 && rrx1<=(midC+7))) && ((rry1<dis_top) && (rry1>0))) { + lcd_mutex.lock(); + uLCD.cls(); + uLCD.text_width(2); //2X size text + uLCD.text_height(2); + uLCD.color(RED); + uLCD.locate(2,2); + uLCD.printf("\n GAME \n OVER!\n"); + wait(.05); + + lcd_mutex.unlock(); + break; + } + + //circle 3 + if( (((midC-7)<=rrrx2 && rrrx2<=(midC+7)) || ((midC-7)<=rrrx1 && rrrx1<=(midC+7))) && ((rrry1<dis_top) && (rrry1>0))) { + lcd_mutex.lock(); + uLCD.cls(); + uLCD.text_width(2); //2X size text + uLCD.text_height(2); + uLCD.color(RED); + uLCD.locate(2,2); + uLCD.printf("\n GAME \n OVER!\n"); + FILE *wave_file; + wave_file=fopen("/sd/mydir/loser.wav","r"); + waver.play(wave_file); + fclose(wave_file); + wait(2); + + lcd_mutex.unlock(); + break; + } + + length = length +1; //increment lenght or duration of the number of scrolls it goes through + Thread::wait(500); + + // Begin the final fall to the ground + if(length>=stopLength+15 && circY<109){ + + + //displays text to hit fire while falling until you hit fire and deploy the parachute + if(count==0){ + lcd_mutex.lock(); + uLCD.text_width(1); //2X size text + uLCD.text_height(1); + uLCD.color(GREEN); + uLCD.locate(2,2); + uLCD.printf("\n Hit fire for \n a parachute! \n"); + //wait(2); + lcd_mutex.unlock(); + } + + lcd_mutex.lock(); + uLCD.filled_rectangle(0, 128, 128, 118,GREEN); + uLCD.filled_rectangle(90, 123, 105, 118,RED); + + if(parachute==1){ + uLCD.triangle(midC-10,circY -25, midC+10, circY -25, midC, circY -7, BLUE); + } + uLCD.filled_circle(midC, circY, 7, BLUE); + midC = midC-1; + circY = circY + 2; + if(parachute==1){ + uLCD.triangle(midC-10,circY -25, midC+10, circY -25, midC, circY -7, BLACK); + } + uLCD.filled_circle(midC, circY, 7, BLACK); + + lcd_mutex.unlock();//release lock + + //if fire is pressed then parachute is deployed + if(myNav.fire() == 1){ + parachute = 1; + lcd_mutex.lock(); + uLCD.triangle(midC-10,circY -25, midC+10, circY -25, midC, circY -7, BLACK); + uLCD.text_width(1); //2X size text + uLCD.text_height(1); + uLCD.color(BLUE); + uLCD.locate(2,2); + uLCD.printf("\n Hit fire for \n a parachute! \n"); + count = 1; + lcd_mutex.unlock(); + } + + //checking to see if the botton of the circle touched the red space...if so you win + if(circY+7==117 && (midC<=105 && midC>=90)) { + lcd_mutex.lock(); + uLCD.text_width(2); //2X size text + uLCD.text_height(2); + uLCD.color(GREEN); + uLCD.locate(2,2); + if(parachute == 1) { + uLCD.printf("\n You \n WON!\n"); + ///////////////////////////////////////////////////////SDcard reading from sound for winning!!!! + FILE *wave_file; + wave_file=fopen("/sd/mydir/yababy.wav","r"); + waver.play(wave_file); + fclose(wave_file); + } + + //if you don't deploy your parachute but still land ont he red, you still lose + if(parachute == 0) { + uLCD.printf("\n You \n lost.\n"); + // SDcard reading for losing + FILE *wave_file; + wave_file=fopen("/sd/mydir/loser.wav","r"); + waver.play(wave_file); + fclose(wave_file); + } + lcd_mutex.unlock(); + } + + //checks to see if you touch green part of the ground + if(circY+7>=117 && (midC>105 || midC<90)) { + lcd_mutex.lock(); + uLCD.text_width(2); //2X size text + uLCD.text_height(2); + uLCD.color(GREEN); + uLCD.locate(2,2); + uLCD.printf("\n You \n lost.\n"); + // SDcard reading for losing + FILE *wave_file; + wave_file=fopen("/sd/mydir/loser.wav","r"); + waver.play(wave_file); + fclose(wave_file); + //wait(2); + lcd_mutex.unlock(); + } + } + } +} + +/*// Sound Thread for Wind +void thread2(void const *args) { + if(parachute == 1) { + FILE *wave_file; + wave_file=fopen("/sd/mydir/Wind.wav","r"); + waver.play(wave_file); + fclose(wave_file); + } +}*/ + +int main() { + + //uLCD.text_mode(OPAQUE); + // Initial start screen and countdown to beginning of game + uLCD.printf("\nSkydiving!\n"); //Default Green on black text + uLCD.printf("\n Starting Game \nShortly..."); + uLCD.text_width(4); //4X size text + uLCD.text_height(4); + uLCD.color(RED); + wait(2); + for (int i=3; i>=0; --i) { + uLCD.locate(1,2); + uLCD.printf("%2D",i); + wait(1); + } + 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); + + + + //initialization of variables + circY = 8; + rx1 = 10; + ry1 = 160; + rrx1 = 50; + rry1 = 128; + rrrx1 = 100; + rrry1 = 200; + + tx1=10; + ty1=30; + + lx1 = 25; + ly1 = 130; + + + length =0; + midC = 64; + breakT = 0; + stopLength = 50; + shapeColor1 = 0x66FF33; + + uLCD.filled_circle(midC, 8, 7, BLACK); // draw initial skydiver + + + // draw initial obstacles + uLCD.filled_rectangle(rx1, ry1, rx1+10, ry1+10, WHITE); + uLCD.filled_rectangle(rrx1, rry1, rrx1+10, rry1+10, WHITE); + uLCD.filled_rectangle(rrrx1, rrry1, rrrx1+10, rrry1+10, WHITE); + + uLCD.filled_circle(midC, circY, 7, BLACK); + + ///// Sound of Scream jumping out of Airplane + FILE *wave_file; + wave_file=fopen("/sd/mydir/scream_male.wav","r"); + waver.play(wave_file); + fclose(wave_file); + //// End Scream + Thread t1(thread1); + //Thread t2(thread2); + + while(true) { + if(breakT ==1){ + uLCD.cls(); + uLCD.filled_circle(midC, circY, 7, BLACK); + } + + + //control if nav switch is switch left + if(myNav.left() == 0x01){ + lcd_mutex.lock();//acquire lock + if(parachute==1){ + uLCD.triangle(midC-10,circY -25, midC+10, circY -25, midC, circY -7, BLUE); + } + uLCD.filled_circle(midC, circY, 7, BLUE); + if((midC-1)<=7){ + midC = 7; + } + else{ + midC = midC-1; + } + if(parachute==1){ + uLCD.triangle(midC-10,circY -25, midC+10, circY -25, midC, circY -7, BLACK); + } + uLCD.filled_circle(midC, circY, 7, BLACK); + lcd_mutex.unlock();//release lock + } + + //control if nav switch is switched right + if(myNav.right() == 0x01){ + lcd_mutex.lock();//acquire lock + if(parachute==1){ + uLCD.triangle(midC-10,circY -25, midC+10, circY -25, midC, circY -7, BLUE); + } + uLCD.filled_circle(midC, circY, 7, BLUE); + if((midC+1)>=120){ + midC = 120; + } + else{ + midC = midC+1; + } + if(parachute==1){ + uLCD.triangle(midC-10,circY -25, midC+10, circY -25, midC, circY -7, BLACK); + } + uLCD.filled_circle(midC, circY, 7, BLACK); + lcd_mutex.unlock();//release lock + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-rtos.lib Wed Mar 16 20:13:23 2016 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed-rtos/#b4c5542476ba
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Wed Mar 16 20:13:23 2016 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/87f2f5183dfb \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wave_player.lib Wed Mar 16 20:13:23 2016 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/sravet/code/wave_player/#acc3e18e77ad