A implementation of a simple bomberman game
Dependencies: 4DGL-uLCD-SE SDFileSystem mbed-rtos mbed wave_player
Fork of rtos_basic by
main.cpp
00001 #include "mbed.h" 00002 #include "SDFileSystem.h" 00003 #include "wave_player.h" 00004 #include "myBMP.h" 00005 #include <string> 00006 #include "navSwitch.h" 00007 #include <mpr121.h> 00008 #include "rtos.h" 00009 00010 float gameTime = 0.0; 00011 00012 string startText = "Loading"; 00013 00014 bool gameRestart = false; 00015 00016 SDFileSystem sd(p11, p12, p13, p16, "sd"); //SD card 00017 00018 AnalogOut DACout(p18); 00019 00020 wave_player waver(&DACout); 00021 00022 uLCD_4DGL uLCD(p28,p27,p30); 00023 00024 int BACK = 0x2E0059; 00025 00026 char grid[7][7]; 00027 00028 int o_p1I=0, o_p1J=0, o_p2I=6, o_p2J=6; 00029 int p1I=0, p1J=0, p2I=6, p2J=6; 00030 00031 Nav_Switch myNav( p17, p6, p7, p5, p8); 00032 bool navUpPress = false, navLeftPress = false, 00033 navRightPress = false, navDownPress = false, navFirePress = false; 00034 00035 I2C i2c(p9, p10); 00036 Mpr121 pad(&i2c, Mpr121::ADD_VSS); 00037 00038 bool padUpPress = false, padLeftPress = false, 00039 padRightPress = false, padDownPress = false, padFirePress = false; 00040 00041 struct Bomb { 00042 float createTime; 00043 int playerId; 00044 int startI, startJ; 00045 int power; 00046 int minX, maxX, minY, maxY; 00047 bool exploded, soundPlayed; 00048 float cookTime, expTime; 00049 int decay,color; 00050 int o_decay; 00051 }; 00052 00053 Bomb bombs[10]; 00054 int bombIndex=0, numBombs = 0; 00055 int bufferSize = 10; 00056 00057 int p1Bombs=1, p2Bombs=1; 00058 int p1Power=1, p2Power=1; 00059 00060 void resetVars(){ 00061 gameRestart = false; 00062 00063 o_p1I=0; 00064 o_p1J=0; 00065 o_p2I=6; 00066 o_p2J=6; 00067 p1I=0; 00068 p1J=0; 00069 p2I=6; 00070 p2J=6; 00071 00072 numBombs = 0; 00073 bombIndex = 0; 00074 00075 p1Bombs = 1; 00076 p1Power = 1; 00077 p2Bombs = 1; 00078 p2Power = 1; 00079 } 00080 00081 bool outOfBounds(int i, int j){ 00082 return i < 0 || i > 6 || j < 0 || j > 6; 00083 } 00084 00085 bool valid(int i, int j) 00086 { 00087 if(outOfBounds(i,j)){ 00088 return false; 00089 } 00090 00091 return grid[i][j] != 'b' && grid[i][j] != 's'; 00092 } 00093 00094 int getX(int j) 00095 { 00096 return 8+16*j; 00097 } 00098 00099 int getY(int i) 00100 { 00101 return 8+16*i; 00102 } 00103 00104 void createBomb(int pId, int i, int j) 00105 { 00106 Bomb *b = &bombs[(bombIndex + numBombs)%bufferSize]; 00107 numBombs++; 00108 00109 b->playerId = pId; 00110 b->createTime = gameTime; 00111 b->startI = i; 00112 b->startJ = j; 00113 b->power = (pId == 1)? p1Power : p2Power; 00114 if(pId == 1) { 00115 p1Bombs--; 00116 } else { 00117 p2Bombs--; 00118 } 00119 b->exploded = false; 00120 b->cookTime = 1.5; 00121 b->expTime = .8; 00122 b->decay = 0; 00123 b->o_decay = 0; 00124 b->soundPlayed = false; 00125 } 00126 00127 void resetBlock(int i, int j){ 00128 if(grid[i][j] == ' '){ 00129 grid[i][j] = 'c'; 00130 return; 00131 } 00132 int rr = (int)(gameTime * 1000) + 1023 * i + 523 * j; 00133 if(rr%3 == 0){ 00134 grid[i][j] = 'k'; 00135 }else if(rr%3 == 1){ 00136 grid[i][j] = 'd'; 00137 }else{ 00138 grid[i][j] = 'c'; 00139 } 00140 } 00141 00142 void clearArea(Bomb *b) 00143 { 00144 //find minX 00145 int p = b->power; 00146 int i = b->startI; 00147 int j = b->startJ; 00148 while(p>0) { 00149 if(outOfBounds(i,j-1) || grid[i][j-1] == 's') { 00150 break; 00151 } 00152 resetBlock(i,j-1); 00153 j--; 00154 p--; 00155 } 00156 b->minX = getX(j) + ((p==0)?3:0); 00157 00158 //find maxX 00159 p = b->power; 00160 i = b->startI; 00161 j = b->startJ; 00162 while(p>0) { 00163 if(outOfBounds(i,j+1) || grid[i][j+1] == 's') { 00164 break; 00165 } 00166 resetBlock(i,j+1); 00167 j++; 00168 p--; 00169 } 00170 b->maxX = getX(j+1)+((p==0)?-3:0); 00171 00172 //find minY 00173 p = b->power; 00174 i = b->startI; 00175 j = b->startJ; 00176 while(p>0) { 00177 if(outOfBounds(i-1,j) || grid[i-1][j] == 's') { 00178 break; 00179 } 00180 resetBlock(i-1,j); 00181 i--; 00182 p--; 00183 } 00184 b->minY = getY(i) + ((p==0)?3:0); 00185 00186 //find maxY 00187 p = b->power; 00188 i = b->startI; 00189 j = b->startJ; 00190 while(p>0) { 00191 if(outOfBounds(i+1,j) || grid[i+1][j] == 's') { 00192 break; 00193 } 00194 resetBlock(i+1,j); 00195 i++; 00196 p--; 00197 } 00198 b->maxY = getY(i+1) + ((p==0)?-3:0); 00199 } 00200 00201 void playExplosion() 00202 { 00203 while(true){ 00204 bool expFound = false; 00205 while(!expFound){ 00206 for(int i = 0; i < numBombs; i++) { 00207 Bomb *b = &bombs[(bombIndex + i)%bufferSize]; 00208 if(b->exploded && !b->soundPlayed){ 00209 expFound = true; 00210 b->soundPlayed = true; 00211 } 00212 } 00213 Thread::wait(100); 00214 } 00215 FILE *explosion; 00216 explosion=fopen("/sd/explosion.wav","r"); 00217 waver.play(explosion); 00218 fclose(explosion); 00219 } 00220 } 00221 00222 void updateBombs() 00223 { 00224 for(int i = 0; i < numBombs; i++) { 00225 Bomb *b = &bombs[(bombIndex + i)%bufferSize]; 00226 if(!b->exploded && (gameTime - b->createTime) > b->cookTime) { 00227 b->exploded = true; 00228 clearArea(b); 00229 00230 } 00231 if(!b->exploded) { 00232 int index = (int)((gameTime - b->createTime)/.15); 00233 if((index & 0x11) == 0) { 00234 b->color = WHITE; 00235 } else { 00236 b->color = BLACK; 00237 } 00238 } else { 00239 int index = (int)((gameTime - b->createTime - b->cookTime)/.2); 00240 if(index == 0) { 00241 b->color = WHITE; 00242 } 00243 if(index == 1) { 00244 b->color = 0xFFFF00; 00245 } 00246 if(index == 2) { 00247 b->color = 0xFF8800; 00248 } 00249 if(index >= 3) { 00250 b->color = RED; 00251 } 00252 index = (int)((gameTime - b->createTime - b->cookTime)/.25); 00253 b->decay = index; 00254 } 00255 } 00256 } 00257 00258 void drawBombs() 00259 { 00260 for(int i = 0; i < numBombs; i++) { 00261 Bomb *b = &bombs[(bombIndex + i)%bufferSize]; 00262 int x = getX(b->startJ); 00263 int y = getY(b->startI); 00264 if(!b->exploded) { 00265 if(b->color == WHITE) { 00266 uLCD.filled_circle(x+8,y+8,5, WHITE); 00267 uLCD.filled_rectangle(x+7,y+1,x+9,y+3, WHITE); 00268 } else { 00269 uLCD.filled_circle(x+8,y+8,5, BLACK); 00270 uLCD.filled_rectangle(x+7,y+1,x+9,y+3, 0xFFFF00); 00271 } 00272 } else { 00273 if(b->o_decay != b->decay){ 00274 b->o_decay = b->decay; 00275 uLCD.filled_rectangle(b->minX,y+3,b->maxX,y+13, BACK); 00276 uLCD.filled_rectangle(x+3,b->minY,x+13,b->maxY, BACK); 00277 } 00278 00279 if(gameTime - b->createTime < (b->cookTime + b->expTime)) { 00280 uLCD.filled_rectangle(b->minX+b->decay,y+3+b->decay,b->maxX-b->decay,y+13-b->decay, b->color); 00281 uLCD.filled_rectangle(x+3+b->decay,b->minY+b->decay,x+13-b->decay,b->maxY-b->decay, b->color); 00282 } else { 00283 uLCD.filled_rectangle(b->minX,y+3,b->maxX,y+13, BACK); 00284 uLCD.filled_rectangle(x+3,b->minY,x+13,b->maxY, BACK); 00285 if(b->playerId == 1) { 00286 p1Bombs++; 00287 } else { 00288 p2Bombs++; 00289 } 00290 bombIndex=(bombIndex+1)%bufferSize; 00291 numBombs--; 00292 } 00293 } 00294 } 00295 } 00296 00297 void generateGrid() 00298 { 00299 //init empty 00300 for(int i = 0; i < 7; i++) { 00301 for(int j = 0; j < 7; j++) { 00302 grid[i][j] = ' '; 00303 } 00304 } 00305 //generate solids 00306 for(int i = 1; i < 7; i+=2) { 00307 for(int j = 1; j < 7; j+=2) { 00308 grid[i][j] = 's'; 00309 } 00310 } 00311 //generate breakables 00312 for(int i = 0; i < 7; i++) { 00313 for(int j = 0; j < 7; j++) { 00314 if(grid[i][j] == 's') { 00315 continue; 00316 } 00317 bool hasBreakable = (i*17+j*349)%4 != 0; 00318 if(hasBreakable) { 00319 grid[i][j] = 'b'; 00320 } 00321 } 00322 } 00323 //clear player regions 00324 grid[0][0] = ' '; 00325 grid[1][0] = ' '; 00326 grid[0][1] = ' '; 00327 grid[6][6] = ' '; 00328 grid[5][6] = ' '; 00329 grid[6][5] = ' '; 00330 } 00331 00332 void drawImg(string imgName, int x, int y) 00333 { 00334 RGBApixel *Colors = new RGBApixel [2]; 00335 string file = "/sd/" + imgName; 00336 ReadBMPFromFile(x,y, file.c_str(), Colors, &uLCD); 00337 } 00338 00339 void drawPlayer(int id) 00340 { 00341 int col_prim, col_sec, x, y; 00342 if(id == 1) { 00343 col_prim = 0xFFD8B2; 00344 col_sec = 0xFFB2B2; 00345 x = getX(p1J); 00346 y = getY(p1I); 00347 } 00348 if(id == 2) { 00349 col_prim = 0xC6B2FF; 00350 col_sec = 0xFFB2FF; 00351 x = getX(p2J); 00352 y = getY(p2I); 00353 } 00354 uLCD.filled_rectangle(x+3,y+3,x+13,y+10, col_prim); 00355 uLCD.filled_rectangle(x+5,y+5,x+6,y+8, BLACK); 00356 uLCD.filled_rectangle(x+10,y+5,x+11,y+8, BLACK); 00357 uLCD.filled_rectangle(x+5,y+10,x+7,y+13, col_sec); 00358 uLCD.filled_rectangle(x+9,y+10,x+11,y+13, col_sec); 00359 } 00360 00361 void initialDraw() 00362 { 00363 uLCD.baudrate(3000000); 00364 uLCD.filled_rectangle(0,0,128,128, BACK); 00365 uLCD.text_width(2); 00366 uLCD.text_height(2); 00367 uLCD.color(WHITE); 00368 uLCD.locate(1,4); 00369 uLCD.printf("%s",startText); 00370 for(int i = -1; i < 8; i++){ 00371 for(int j = -1; j < 8; j++){ 00372 string img; 00373 int c = -1; 00374 if(i == -1 || j == -1 || i == 7 || j == 7){ 00375 img = "wall.bmp"; 00376 //c = BLACK; 00377 }else{ 00378 if(grid[i][j] == ' '){ 00379 c = BACK; 00380 } 00381 if(grid[i][j] == 'b'){ 00382 img = "break.bmp"; 00383 //c = 0x888888; 00384 } 00385 if(grid[i][j] == 's'){ 00386 img = "wall.bmp"; 00387 //c = BLACK; 00388 } 00389 } 00390 int x = getX(j); 00391 int y = getY(i); 00392 if(c != -1){ 00393 uLCD.filled_rectangle(x,y,x+16,y+16, c); 00394 }else{ 00395 drawImg(img, x, y); 00396 } 00397 00398 } 00399 } 00400 drawPlayer(1); 00401 drawPlayer(2); 00402 } 00403 00404 00405 void updateP1() 00406 { 00407 if(!navUpPress && myNav.up()) { 00408 p1I++; 00409 navUpPress = true; 00410 } 00411 if(!navDownPress && myNav.down()) { 00412 p1I--; 00413 navDownPress = true; 00414 } 00415 if(!navLeftPress && myNav.left()) { 00416 p1J++; 00417 navLeftPress = true; 00418 } 00419 if(!navRightPress && myNav.right()) { 00420 p1J--; 00421 navRightPress = true; 00422 } 00423 if(!navFirePress && myNav.fire() && p1Bombs >0) { 00424 createBomb(1,p1I,p1J); 00425 navFirePress = true; 00426 } 00427 00428 if(!valid(p1I,p1J)) { 00429 p1I = o_p1I; 00430 p1J = o_p1J; 00431 } 00432 00433 if(grid[p1I][p1J] == 'f'){ 00434 p1Power++; 00435 grid[p1I][p1J] = 'c'; 00436 } 00437 if(grid[p1I][p1J] == 'i'){ 00438 p1Bombs++; 00439 grid[p1I][p1J] = 'c'; 00440 } 00441 00442 if(!myNav.up()) { 00443 navUpPress = false; 00444 } 00445 if(!myNav.down()) { 00446 navDownPress = false; 00447 } 00448 if(!myNav.left()) { 00449 navLeftPress = false; 00450 } 00451 if(!myNav.right()) { 00452 navRightPress = false; 00453 } 00454 if(!myNav.fire()) { 00455 navFirePress = false; 00456 } 00457 } 00458 00459 bool isOne(int val, int pos) 00460 { 00461 return val >> pos & 0x01; 00462 } 00463 00464 void updateP2() 00465 { 00466 int value=pad.read(0x00); 00467 value +=pad.read(0x01)<<8; 00468 00469 bool up = isOne(value,5); 00470 bool down = isOne(value,7); 00471 bool left = isOne(value,10); 00472 bool right = isOne(value,2); 00473 bool fire = isOne(value,6); 00474 00475 if(!padUpPress && up) { 00476 p2I--; 00477 padUpPress = true; 00478 } 00479 if(!padDownPress && down) { 00480 p2I++; 00481 padDownPress = true; 00482 } 00483 if(!padLeftPress && left) { 00484 p2J--; 00485 padLeftPress = true; 00486 } 00487 if(!padRightPress && right) { 00488 p2J++; 00489 padRightPress = true; 00490 } 00491 if(!padFirePress && fire && p2Bombs > 0) { 00492 createBomb(2,p2I,p2J); 00493 padFirePress = true; 00494 } 00495 00496 if(!valid(p2I,p2J)) { 00497 p2I = o_p2I; 00498 p2J = o_p2J; 00499 } 00500 00501 if(grid[p2I][p2J] == 'f'){ 00502 p2Power++; 00503 grid[p2I][p2J] = 'c'; 00504 } 00505 if(grid[p2I][p2J] == 'i'){ 00506 p2Bombs++; 00507 grid[p2I][p2J] = 'c'; 00508 } 00509 00510 if(!up) { 00511 padUpPress = false; 00512 } 00513 if(!down) { 00514 padDownPress = false; 00515 } 00516 if(!left) { 00517 padLeftPress = false; 00518 } 00519 if(!right) { 00520 padRightPress = false; 00521 } 00522 if(!fire) { 00523 padFirePress = false; 00524 } 00525 } 00526 00527 void draw() 00528 { 00529 for(int i = 0; i < 7; i++){ 00530 for(int j = 0; j < 7; j++){ 00531 if(grid[i][j] == 'c' || grid[i][j] == 'd' || grid[i][j] == 'k'){ 00532 if(grid[i][j] == 'c') grid[i][j] = ' '; 00533 if(grid[i][j] == 'd') grid[i][j] = 'f'; 00534 if(grid[i][j] == 'k') grid[i][j] = 'i'; 00535 uLCD.filled_rectangle(getX(j),getY(i),getX(j+1),getY(i+1), BACK); 00536 } 00537 if(grid[i][j] == 'f'){ 00538 uLCD.filled_circle(getX(j)+8,getY(i)+8,3,RED); 00539 } 00540 if(grid[i][j] == 'i'){ 00541 uLCD.filled_circle(getX(j)+8,getY(i)+8,3,0xFFFF00); 00542 } 00543 } 00544 } 00545 if(p1I != o_p1I || p1J != o_p1J) { 00546 int o_x = getX(o_p1J); 00547 int o_y = getY(o_p1I); 00548 uLCD.filled_rectangle(o_x,o_y,o_x+16,o_y+16, BACK); 00549 o_p1I = p1I; 00550 o_p1J = p1J; 00551 } 00552 if(p2I != o_p2I || p2J != o_p2J) { 00553 int o_x = getX(o_p2J); 00554 int o_y = getY(o_p2I); 00555 uLCD.filled_rectangle(o_x,o_y,o_x+16,o_y+16, BACK); 00556 o_p2I = p2I; 00557 o_p2J = p2J; 00558 } 00559 drawBombs(); 00560 drawPlayer(1); 00561 drawPlayer(2); 00562 } 00563 00564 void checkPlayerDeath(int pid){ 00565 if(gameRestart) return; 00566 int centerX = getX((pid == 1)?(p1J):(p2J))+8; 00567 int centerY = getY((pid == 1)?(p1I):(p2I))+8; 00568 for(int i = 0; i < numBombs; i++) { 00569 Bomb *b = &bombs[(bombIndex + i)%bufferSize]; 00570 if(b->exploded){ 00571 int bx = getX(b->startJ); 00572 int by = getY(b->startI); 00573 if(b->minX < centerX && centerX < b->maxX && by < centerY && centerY < by+16){ 00574 gameRestart = true; 00575 } 00576 if(b->minY < centerY && centerY < b->maxY && bx < centerX && centerX < bx+16){ 00577 gameRestart = true; 00578 } 00579 } 00580 } 00581 if(gameRestart){ 00582 if(pid == 1){ 00583 startText = "P1 Died"; 00584 }else{ 00585 startText = "P2 Died"; 00586 } 00587 } 00588 } 00589 00590 int main() 00591 { 00592 Thread thr(playExplosion); 00593 while(true){ 00594 resetVars(); 00595 generateGrid(); 00596 initialDraw(); 00597 while(!gameRestart) { 00598 updateP1(); 00599 updateP2(); 00600 updateBombs(); 00601 checkPlayerDeath(1); 00602 checkPlayerDeath(2); 00603 draw(); 00604 gameTime+=.02; 00605 wait(.02); 00606 } 00607 wait(3); 00608 } 00609 }
Generated on Thu Jul 14 2022 17:13:56 by 1.7.2