A implementation of a simple bomberman game
Dependencies: 4DGL-uLCD-SE SDFileSystem mbed-rtos mbed wave_player
Fork of rtos_basic by
main.cpp
- Committer:
- apcastelein
- Date:
- 2016-10-31
- Revision:
- 7:12f7fd2b1a13
- Parent:
- 3:c92e21f305d8
File content as of revision 7:12f7fd2b1a13:
#include "mbed.h" #include "SDFileSystem.h" #include "wave_player.h" #include "myBMP.h" #include <string> #include "navSwitch.h" #include <mpr121.h> #include "rtos.h" float gameTime = 0.0; string startText = "Loading"; bool gameRestart = false; SDFileSystem sd(p11, p12, p13, p16, "sd"); //SD card AnalogOut DACout(p18); wave_player waver(&DACout); uLCD_4DGL uLCD(p28,p27,p30); int BACK = 0x2E0059; char grid[7][7]; int o_p1I=0, o_p1J=0, o_p2I=6, o_p2J=6; int p1I=0, p1J=0, p2I=6, p2J=6; Nav_Switch myNav( p17, p6, p7, p5, p8); bool navUpPress = false, navLeftPress = false, navRightPress = false, navDownPress = false, navFirePress = false; I2C i2c(p9, p10); Mpr121 pad(&i2c, Mpr121::ADD_VSS); bool padUpPress = false, padLeftPress = false, padRightPress = false, padDownPress = false, padFirePress = false; struct Bomb { float createTime; int playerId; int startI, startJ; int power; int minX, maxX, minY, maxY; bool exploded, soundPlayed; float cookTime, expTime; int decay,color; int o_decay; }; Bomb bombs[10]; int bombIndex=0, numBombs = 0; int bufferSize = 10; int p1Bombs=1, p2Bombs=1; int p1Power=1, p2Power=1; void resetVars(){ gameRestart = false; o_p1I=0; o_p1J=0; o_p2I=6; o_p2J=6; p1I=0; p1J=0; p2I=6; p2J=6; numBombs = 0; bombIndex = 0; p1Bombs = 1; p1Power = 1; p2Bombs = 1; p2Power = 1; } bool outOfBounds(int i, int j){ return i < 0 || i > 6 || j < 0 || j > 6; } bool valid(int i, int j) { if(outOfBounds(i,j)){ return false; } return grid[i][j] != 'b' && grid[i][j] != 's'; } int getX(int j) { return 8+16*j; } int getY(int i) { return 8+16*i; } void createBomb(int pId, int i, int j) { Bomb *b = &bombs[(bombIndex + numBombs)%bufferSize]; numBombs++; b->playerId = pId; b->createTime = gameTime; b->startI = i; b->startJ = j; b->power = (pId == 1)? p1Power : p2Power; if(pId == 1) { p1Bombs--; } else { p2Bombs--; } b->exploded = false; b->cookTime = 1.5; b->expTime = .8; b->decay = 0; b->o_decay = 0; b->soundPlayed = false; } void resetBlock(int i, int j){ if(grid[i][j] == ' '){ grid[i][j] = 'c'; return; } int rr = (int)(gameTime * 1000) + 1023 * i + 523 * j; if(rr%3 == 0){ grid[i][j] = 'k'; }else if(rr%3 == 1){ grid[i][j] = 'd'; }else{ grid[i][j] = 'c'; } } void clearArea(Bomb *b) { //find minX int p = b->power; int i = b->startI; int j = b->startJ; while(p>0) { if(outOfBounds(i,j-1) || grid[i][j-1] == 's') { break; } resetBlock(i,j-1); j--; p--; } b->minX = getX(j) + ((p==0)?3:0); //find maxX p = b->power; i = b->startI; j = b->startJ; while(p>0) { if(outOfBounds(i,j+1) || grid[i][j+1] == 's') { break; } resetBlock(i,j+1); j++; p--; } b->maxX = getX(j+1)+((p==0)?-3:0); //find minY p = b->power; i = b->startI; j = b->startJ; while(p>0) { if(outOfBounds(i-1,j) || grid[i-1][j] == 's') { break; } resetBlock(i-1,j); i--; p--; } b->minY = getY(i) + ((p==0)?3:0); //find maxY p = b->power; i = b->startI; j = b->startJ; while(p>0) { if(outOfBounds(i+1,j) || grid[i+1][j] == 's') { break; } resetBlock(i+1,j); i++; p--; } b->maxY = getY(i+1) + ((p==0)?-3:0); } void playExplosion() { while(true){ bool expFound = false; while(!expFound){ for(int i = 0; i < numBombs; i++) { Bomb *b = &bombs[(bombIndex + i)%bufferSize]; if(b->exploded && !b->soundPlayed){ expFound = true; b->soundPlayed = true; } } Thread::wait(100); } FILE *explosion; explosion=fopen("/sd/explosion.wav","r"); waver.play(explosion); fclose(explosion); } } void updateBombs() { for(int i = 0; i < numBombs; i++) { Bomb *b = &bombs[(bombIndex + i)%bufferSize]; if(!b->exploded && (gameTime - b->createTime) > b->cookTime) { b->exploded = true; clearArea(b); } if(!b->exploded) { int index = (int)((gameTime - b->createTime)/.15); if((index & 0x11) == 0) { b->color = WHITE; } else { b->color = BLACK; } } else { int index = (int)((gameTime - b->createTime - b->cookTime)/.2); if(index == 0) { b->color = WHITE; } if(index == 1) { b->color = 0xFFFF00; } if(index == 2) { b->color = 0xFF8800; } if(index >= 3) { b->color = RED; } index = (int)((gameTime - b->createTime - b->cookTime)/.25); b->decay = index; } } } void drawBombs() { for(int i = 0; i < numBombs; i++) { Bomb *b = &bombs[(bombIndex + i)%bufferSize]; int x = getX(b->startJ); int y = getY(b->startI); if(!b->exploded) { if(b->color == WHITE) { uLCD.filled_circle(x+8,y+8,5, WHITE); uLCD.filled_rectangle(x+7,y+1,x+9,y+3, WHITE); } else { uLCD.filled_circle(x+8,y+8,5, BLACK); uLCD.filled_rectangle(x+7,y+1,x+9,y+3, 0xFFFF00); } } else { if(b->o_decay != b->decay){ b->o_decay = b->decay; uLCD.filled_rectangle(b->minX,y+3,b->maxX,y+13, BACK); uLCD.filled_rectangle(x+3,b->minY,x+13,b->maxY, BACK); } if(gameTime - b->createTime < (b->cookTime + b->expTime)) { uLCD.filled_rectangle(b->minX+b->decay,y+3+b->decay,b->maxX-b->decay,y+13-b->decay, b->color); uLCD.filled_rectangle(x+3+b->decay,b->minY+b->decay,x+13-b->decay,b->maxY-b->decay, b->color); } else { uLCD.filled_rectangle(b->minX,y+3,b->maxX,y+13, BACK); uLCD.filled_rectangle(x+3,b->minY,x+13,b->maxY, BACK); if(b->playerId == 1) { p1Bombs++; } else { p2Bombs++; } bombIndex=(bombIndex+1)%bufferSize; numBombs--; } } } } void generateGrid() { //init empty for(int i = 0; i < 7; i++) { for(int j = 0; j < 7; j++) { grid[i][j] = ' '; } } //generate solids for(int i = 1; i < 7; i+=2) { for(int j = 1; j < 7; j+=2) { grid[i][j] = 's'; } } //generate breakables for(int i = 0; i < 7; i++) { for(int j = 0; j < 7; j++) { if(grid[i][j] == 's') { continue; } bool hasBreakable = (i*17+j*349)%4 != 0; if(hasBreakable) { grid[i][j] = 'b'; } } } //clear player regions grid[0][0] = ' '; grid[1][0] = ' '; grid[0][1] = ' '; grid[6][6] = ' '; grid[5][6] = ' '; grid[6][5] = ' '; } void drawImg(string imgName, int x, int y) { RGBApixel *Colors = new RGBApixel [2]; string file = "/sd/" + imgName; ReadBMPFromFile(x,y, file.c_str(), Colors, &uLCD); } void drawPlayer(int id) { int col_prim, col_sec, x, y; if(id == 1) { col_prim = 0xFFD8B2; col_sec = 0xFFB2B2; x = getX(p1J); y = getY(p1I); } if(id == 2) { col_prim = 0xC6B2FF; col_sec = 0xFFB2FF; x = getX(p2J); y = getY(p2I); } uLCD.filled_rectangle(x+3,y+3,x+13,y+10, col_prim); uLCD.filled_rectangle(x+5,y+5,x+6,y+8, BLACK); uLCD.filled_rectangle(x+10,y+5,x+11,y+8, BLACK); uLCD.filled_rectangle(x+5,y+10,x+7,y+13, col_sec); uLCD.filled_rectangle(x+9,y+10,x+11,y+13, col_sec); } void initialDraw() { uLCD.baudrate(3000000); uLCD.filled_rectangle(0,0,128,128, BACK); uLCD.text_width(2); uLCD.text_height(2); uLCD.color(WHITE); uLCD.locate(1,4); uLCD.printf("%s",startText); for(int i = -1; i < 8; i++){ for(int j = -1; j < 8; j++){ string img; int c = -1; if(i == -1 || j == -1 || i == 7 || j == 7){ img = "wall.bmp"; //c = BLACK; }else{ if(grid[i][j] == ' '){ c = BACK; } if(grid[i][j] == 'b'){ img = "break.bmp"; //c = 0x888888; } if(grid[i][j] == 's'){ img = "wall.bmp"; //c = BLACK; } } int x = getX(j); int y = getY(i); if(c != -1){ uLCD.filled_rectangle(x,y,x+16,y+16, c); }else{ drawImg(img, x, y); } } } drawPlayer(1); drawPlayer(2); } void updateP1() { if(!navUpPress && myNav.up()) { p1I++; navUpPress = true; } if(!navDownPress && myNav.down()) { p1I--; navDownPress = true; } if(!navLeftPress && myNav.left()) { p1J++; navLeftPress = true; } if(!navRightPress && myNav.right()) { p1J--; navRightPress = true; } if(!navFirePress && myNav.fire() && p1Bombs >0) { createBomb(1,p1I,p1J); navFirePress = true; } if(!valid(p1I,p1J)) { p1I = o_p1I; p1J = o_p1J; } if(grid[p1I][p1J] == 'f'){ p1Power++; grid[p1I][p1J] = 'c'; } if(grid[p1I][p1J] == 'i'){ p1Bombs++; grid[p1I][p1J] = 'c'; } if(!myNav.up()) { navUpPress = false; } if(!myNav.down()) { navDownPress = false; } if(!myNav.left()) { navLeftPress = false; } if(!myNav.right()) { navRightPress = false; } if(!myNav.fire()) { navFirePress = false; } } bool isOne(int val, int pos) { return val >> pos & 0x01; } void updateP2() { int value=pad.read(0x00); value +=pad.read(0x01)<<8; bool up = isOne(value,5); bool down = isOne(value,7); bool left = isOne(value,10); bool right = isOne(value,2); bool fire = isOne(value,6); if(!padUpPress && up) { p2I--; padUpPress = true; } if(!padDownPress && down) { p2I++; padDownPress = true; } if(!padLeftPress && left) { p2J--; padLeftPress = true; } if(!padRightPress && right) { p2J++; padRightPress = true; } if(!padFirePress && fire && p2Bombs > 0) { createBomb(2,p2I,p2J); padFirePress = true; } if(!valid(p2I,p2J)) { p2I = o_p2I; p2J = o_p2J; } if(grid[p2I][p2J] == 'f'){ p2Power++; grid[p2I][p2J] = 'c'; } if(grid[p2I][p2J] == 'i'){ p2Bombs++; grid[p2I][p2J] = 'c'; } if(!up) { padUpPress = false; } if(!down) { padDownPress = false; } if(!left) { padLeftPress = false; } if(!right) { padRightPress = false; } if(!fire) { padFirePress = false; } } void draw() { for(int i = 0; i < 7; i++){ for(int j = 0; j < 7; j++){ if(grid[i][j] == 'c' || grid[i][j] == 'd' || grid[i][j] == 'k'){ if(grid[i][j] == 'c') grid[i][j] = ' '; if(grid[i][j] == 'd') grid[i][j] = 'f'; if(grid[i][j] == 'k') grid[i][j] = 'i'; uLCD.filled_rectangle(getX(j),getY(i),getX(j+1),getY(i+1), BACK); } if(grid[i][j] == 'f'){ uLCD.filled_circle(getX(j)+8,getY(i)+8,3,RED); } if(grid[i][j] == 'i'){ uLCD.filled_circle(getX(j)+8,getY(i)+8,3,0xFFFF00); } } } if(p1I != o_p1I || p1J != o_p1J) { int o_x = getX(o_p1J); int o_y = getY(o_p1I); uLCD.filled_rectangle(o_x,o_y,o_x+16,o_y+16, BACK); o_p1I = p1I; o_p1J = p1J; } if(p2I != o_p2I || p2J != o_p2J) { int o_x = getX(o_p2J); int o_y = getY(o_p2I); uLCD.filled_rectangle(o_x,o_y,o_x+16,o_y+16, BACK); o_p2I = p2I; o_p2J = p2J; } drawBombs(); drawPlayer(1); drawPlayer(2); } void checkPlayerDeath(int pid){ if(gameRestart) return; int centerX = getX((pid == 1)?(p1J):(p2J))+8; int centerY = getY((pid == 1)?(p1I):(p2I))+8; for(int i = 0; i < numBombs; i++) { Bomb *b = &bombs[(bombIndex + i)%bufferSize]; if(b->exploded){ int bx = getX(b->startJ); int by = getY(b->startI); if(b->minX < centerX && centerX < b->maxX && by < centerY && centerY < by+16){ gameRestart = true; } if(b->minY < centerY && centerY < b->maxY && bx < centerX && centerX < bx+16){ gameRestart = true; } } } if(gameRestart){ if(pid == 1){ startText = "P1 Died"; }else{ startText = "P2 Died"; } } } int main() { Thread thr(playExplosion); while(true){ resetVars(); generateGrid(); initialDraw(); while(!gameRestart) { updateP1(); updateP2(); updateBombs(); checkPlayerDeath(1); checkPlayerDeath(2); draw(); gameTime+=.02; wait(.02); } wait(3); } }