Mbed Galaga Game

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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include "uLCD_4DGL.h"
00003 #include "wave_player.h"
00004 #include "SDFileSystem.h"
00005 //#include "enemies.h"
00006 #include <vector>
00007 #include "rtos.h"
00008 uLCD_4DGL uLCD(p28,p27,p29);
00009 AnalogOut DACout(p18);
00010 DigitalOut vib(p21);
00011 wave_player waver(&DACout);
00012 SDFileSystem sd(p5, p6, p7, p8, "sd"); // mosi, miso, sck, cs
00013 BusOut mbedleds(LED1,LED2,LED3,LED4);
00014 //BusOut/In is faster than multiple DigitalOut/Ins
00015 int playLaser = 0;int playEnemyExplode = 0;int playerExplode = 0;//variables to trigger the speaker to play sounds
00016 void sdcard_thread(void const *argument)//thread to play the sounds
00017 {
00018     while(1) {
00019 
00020         if(playLaser){//play sound if player fires
00021             FILE *wave_file;
00022             wave_file=fopen("/sd/laser.wav","r");
00023             waver.play(wave_file);
00024             fclose(wave_file);
00025             playLaser = 0;
00026         }
00027         if(playerExplode) { //play sound if player dies
00028             FILE *wave_file;
00029             wave_file=fopen("/sd/Bomb.wav","r");
00030             waver.play(wave_file);
00031             fclose(wave_file);
00032             playerExplode = 0;
00033         }
00034 
00035         if(playEnemyExplode){//play sound if enemies get hit
00036             FILE *wave_file;
00037             wave_file=fopen("/sd/Bombnew.wav","r");
00038             waver.play(wave_file);
00039             fclose(wave_file);
00040             playEnemyExplode = 0;
00041         }    
00042         Thread::wait(50);
00043     }
00044 }
00045 
00046 class Nav_Switch
00047 {
00048 
00049 public:
00050 
00051     Nav_Switch(PinName up,PinName down,PinName left,PinName right,PinName fire);
00052     int read();
00053 //boolean functions to test each switch
00054     bool up();
00055     bool down();
00056     bool left();
00057     bool right();
00058     bool fire();
00059 //automatic read on RHS
00060     operator int ();
00061 //index to any switch array style
00062 
00063     bool operator[](int index) {
00064 
00065         return _pins[index];
00066 
00067     };
00068 
00069 private:
00070 
00071     BusIn _pins;
00072 
00073 
00074 
00075 };
00076 
00077 Nav_Switch::Nav_Switch (PinName up,PinName down,PinName left,PinName right,PinName fire):
00078 
00079     _pins(up, down, left, right, fire)
00080 
00081 {
00082 
00083     _pins.mode(PullUp); //needed if pullups not on board or a bare nav switch is used - delete otherwise
00084 
00085     wait(0.001); //delays just a bit for pullups to pull inputs high
00086 
00087 }
00088 
00089 inline bool Nav_Switch::up()
00090 
00091 {
00092 
00093     return !(_pins[0]);
00094 
00095 }
00096 
00097 inline bool Nav_Switch::down()
00098 
00099 {
00100 
00101     return !(_pins[1]);
00102 
00103 }
00104 
00105 inline bool Nav_Switch::left()
00106 
00107 {
00108 
00109     return !(_pins[2]);
00110 
00111 }
00112 
00113 inline bool Nav_Switch::right()
00114 
00115 {
00116 
00117     return !(_pins[3]);
00118 
00119 }
00120 
00121 inline bool Nav_Switch::fire()
00122 
00123 {
00124 
00125     return !(_pins[4]);
00126 
00127 }
00128 
00129 inline int Nav_Switch::read()
00130 
00131 {
00132 
00133     return _pins.read();
00134 
00135 }
00136 
00137 inline Nav_Switch::operator int ()
00138 
00139 {
00140 
00141     return _pins.read();
00142 
00143 }
00144 
00145 // Declar player dimensions
00146 
00147 int playerWidth = 7;
00148 
00149 int playerHeight = 3;
00150 
00151 int playerDelta = 3;
00152 
00153 int playerXpos = 64;
00154 
00155 int playerYpos = 113;
00156 
00157 #define maxNumPlayerMissiles  5
00158 
00159 #define numEnemies  10
00160 
00161 //struct for missiles
00162 
00163 typedef struct {
00164 
00165     int x;                   ///< The x-coordinate of missile current position
00166 
00167     int y;                   ///< The y-coordinate of missile current position
00168 
00169     int status;   ///< The missile status, see MISSILE_STATUS
00170 
00171 } playerMissile; // infomration about missile position and status
00172 
00173 //struct for enemies
00174 
00175 typedef struct {
00176 
00177     int x;
00178 
00179     int y;
00180 
00181     int size;
00182 
00183     int status;
00184 
00185 } enemy;
00186 
00187 enemy enemies[numEnemies];//create a struct array of enemies
00188 
00189 // initialize the player's position, missile status, draw player, 
00190 
00191 void player_draw(int x, int y, int playerColor) {
00192 
00193     uLCD.filled_rectangle(x, y, x+playerWidth, y+playerHeight, playerColor); 
00194 
00195     uLCD.filled_rectangle(x+playerDelta, y-playerDelta, x+playerWidth-playerDelta, y+playerHeight, playerColor);  
00196 
00197 }
00198 
00199 playerMissile playerMissiles[maxNumPlayerMissiles]; //struct array of player missiles
00200 
00201 //function to fire a missile
00202 
00203 void player_fire(void){
00204 
00205     playerMissile PM;
00206 
00207     PM.x = playerXpos + (playerWidth/2);
00208 
00209     PM.y = playerYpos-playerDelta;
00210 
00211     PM.status = 1;
00212 
00213     for(int i=0;i<maxNumPlayerMissiles;i++){
00214 
00215         if(playerMissiles[i].status==0){
00216 
00217             playerMissiles[i]=PM;
00218 
00219             break;
00220 
00221         }
00222 
00223     }
00224 
00225 }
00226 
00227 //function to update all parts of the game
00228 
00229 void updateGame(){
00230 
00231     for(int i=0;i<maxNumPlayerMissiles;i++){
00232 
00233         // update all missiles
00234 
00235         if(playerMissiles[i].status == 1){
00236 
00237             uLCD.circle(playerMissiles[i].x,playerMissiles[i].y,1,0x0);
00238 
00239             playerMissiles[i].y-=5;
00240 
00241             uLCD.circle(playerMissiles[i].x,playerMissiles[i].y,1,0xFF0000);
00242 
00243         }
00244 
00245         if(playerMissiles[i].y==0 || playerMissiles[i].status==0){
00246 
00247             uLCD.circle(playerMissiles[i].x,playerMissiles[i].y,1,0x0);
00248 
00249            playerMissiles[i].status = 0;
00250 
00251         }
00252 
00253         //update all enemies
00254 
00255         for(int j=0;j<numEnemies;j++){
00256 
00257             if(playerMissiles[i].status==1 && enemies[j].status==1 && playerMissiles[i].x>enemies[j].x && playerMissiles[i].x<enemies[j].x+enemies[j].size && playerMissiles[i].y>enemies[j].y && playerMissiles[i].y<enemies[j].y+enemies[j].size){
00258 
00259                 enemies[j].status = 0;
00260 
00261                 playerMissiles[i].status = 0;
00262 
00263                 playEnemyExplode=1;
00264 
00265                 uLCD.filled_rectangle(enemies[j].x,enemies[j].y,enemies[j].x+enemies[j].size,enemies[j].y+enemies[j].size,0x0);
00266 
00267             }
00268 
00269         }
00270 
00271     }   
00272 
00273 }
00274 
00275 //function to set initial position of enemies
00276 
00277 void enemies_init(void){
00278 
00279     enemies[0].x = 1;enemies[0].y = 1;enemies[0].size = 8;
00280 
00281     enemies[1].x = 26;enemies[1].y = 1;enemies[1].size = 8;
00282 
00283     enemies[2].x = 51;enemies[2].y = 1;enemies[2].size = 8;
00284 
00285     enemies[3].x = 76;enemies[3].y = 1;enemies[3].size = 8;
00286 
00287     enemies[4].x = 101;enemies[4].y = 1;enemies[4].size = 8;
00288 
00289     enemies[5].x = 1;enemies[5].y = 20;enemies[5].size = 8;
00290 
00291     enemies[6].x = 26;enemies[6].y = 20;enemies[6].size = 8;
00292 
00293     enemies[7].x = 51;enemies[7].y = 20;enemies[7].size = 8;
00294 
00295     enemies[8].x = 76;enemies[8].y = 20;enemies[8].size = 8;
00296 
00297     enemies[9].x = 101;enemies[9].y = 20;enemies[9].size = 8;
00298 
00299 }
00300 
00301 Nav_Switch myNav( p15, p12, p13, p11, p14); //pin order on Sparkfun breakout
00302 
00303 
00304 
00305 int main()
00306 
00307 {
00308 
00309     Thread thread1(sdcard_thread);
00310 
00311     int ctr = 0;int distance=5;int vertical = 1;int win = 1;int numDeadEnemies=0;
00312 
00313     //initialize enemy statuses
00314 
00315     enemies[0].status = 1;enemies[1].status = 1;enemies[2].status = 1;enemies[3].status = 1;enemies[4].status = 1;
00316 
00317     enemies[5].status = 1;enemies[6].status = 1;enemies[7].status = 1;enemies[8].status = 1;enemies[9].status = 1;
00318 
00319     enemies_init();
00320 
00321     //draw enemies
00322 
00323     for(int i=0;i<numEnemies;i++){
00324 
00325         uLCD.filled_rectangle(enemies[i].x,enemies[i].y,enemies[i].x+enemies[i].size,enemies[i].y+enemies[i].size,0x00FF00);
00326 
00327     }
00328 
00329     int i;
00330 
00331     while(1) {
00332 
00333         //with pullups a button hit is a "0" - "~" inverts data to leds
00334 
00335         if(ctr%10==0){
00336 
00337             for(i=0;i<numEnemies;i++){
00338 
00339                 if(enemies[i].status!=0){
00340 
00341                     //update enemy positions
00342 
00343                     uLCD.filled_rectangle(enemies[i].x,enemies[i].y,enemies[i].x+enemies[i].size,enemies[i].y+enemies[i].size,0x0);
00344 
00345                     if(vertical<0){enemies[i].x+=distance;}else{enemies[i].y+=5;}
00346 
00347                     uLCD.filled_rectangle(enemies[i].x,enemies[i].y,enemies[i].x+enemies[i].size,enemies[i].y+enemies[i].size,0x00FF00);
00348 
00349                 }
00350 
00351             }
00352 
00353             if(vertical<0){distance*=-1;}vertical*=-1;
00354 
00355         }
00356 
00357         mbedleds = ~(myNav & 0x0F); //update leds with nav switch direction inputs
00358 
00359        if(myNav.fire()){//fire missile
00360 
00361             vib = 1;
00362 
00363             Thread::wait(100);
00364 
00365             vib=0;
00366 
00367             playLaser = 1;
00368 
00369             player_fire();
00370 
00371             mbedleds = 0x0F; //special all leds on case for fire (center button)
00372 
00373         }
00374 
00375        //or use - if(myNav[4]==0) mbedleds = 0x0F; //can index a switch bit like this
00376 
00377         if(myNav.right() && playerXpos <= 110){//player moves right
00378 
00379             player_draw(playerXpos,playerYpos,0x0);
00380 
00381             playerXpos+=5;
00382 
00383         }
00384 
00385         if(myNav.left() && playerXpos >= 0){//player moves left
00386 
00387             player_draw(playerXpos,playerYpos,0x0);
00388 
00389             playerXpos-=5;
00390 
00391         }
00392 
00393         player_draw(playerXpos,playerYpos,0xFFFF00);//draw the player
00394 
00395         updateGame();
00396 
00397         //check if player has been hit
00398 
00399         for(i=0;i<numEnemies;i++){
00400 
00401             if(enemies[i].status==1 && playerXpos>enemies[i].x && playerXpos<enemies[i].x+enemies[i].size && playerYpos>enemies[i].y && playerYpos<enemies[i].y+enemies[i].size){   
00402 
00403                   player_draw(playerXpos,playerYpos,0x0);win=0;playerExplode=1;vib=1;
00404 
00405             }
00406 
00407             if(enemies[i].status==0)numDeadEnemies++;
00408 
00409             if(enemies[i].y>128)enemies[i].y=1;
00410 
00411         } 
00412 
00413         // check for end game conditions
00414 
00415         if(numDeadEnemies==numEnemies){Thread::wait(1000);break;}
00416 
00417         if(!win){Thread::wait(1000);vib=0;playerExplode=0;break;}
00418 
00419         numDeadEnemies = 0;
00420 
00421         ctr++;
00422 
00423         Thread::wait(10);
00424 
00425     }
00426 
00427     uLCD.locate(5,5);
00428 
00429     if(win){
00430 
00431         uLCD.printf("You Win!!");
00432 
00433     }else{
00434 
00435         uLCD.printf("GAME OVER");
00436 
00437     }
00438 
00439 }