Mbed Galaga Game
Dependencies: 4DGL-uLCD-SE SDFileSystem mbed-rtos mbed wave_player
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 }
Generated on Sun Aug 28 2022 20:13:31 by 1.7.2