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

Files at this revision

API Documentation at this revision

Comitter:
mhennessy3
Date:
Wed Mar 16 20:13:23 2016 +0000
Child:
1:d0bc93562029
Commit message:
publish skydiving game 1

Changed in this revision

4DGL-uLCD-SE.lib Show annotated file Show diff for this revision Revisions of this file
SDFileSystem.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-rtos.lib Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
wave_player.lib Show annotated file Show diff for this revision Revisions of this file
--- /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