![](/media/cache/group/default_image.jpg.50x50_q85.jpg)
All there but errors need fixing
Dependencies: mbed
Overview:
Rookie Tetris is a jigsaw style game based on the classic Tetris.
A block will appear at the top of the screen, you must move it (your options for movement are left, right and down - you cannot move up the board). The block will stop when it if placed either on the floor of the board or on-top of another block.
Your goal is to fill a complete row of the board with the blocks; when you do so the row will delete and the pattern above it will drop down. The game is over when your pattern is tall enough to reach to the top of the board!
Controls:
Use the joystick to move your block! Your block cannot move out of the parameters of the board.
Pot 2 controls the contrast of the screen.
TetrisGame/TetrisGame.cpp@25:a7c89c54454a, 2020-06-03 (annotated)
- Committer:
- el18rs
- Date:
- Wed Jun 03 22:26:13 2020 +0000
- Revision:
- 25:a7c89c54454a
- Parent:
- 24:8868a01f4a8c
- Child:
- 26:00e1a6076038
Final Submission
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
el18rs | 3:522c6f850e91 | 1 | #include "TetrisGame.h" |
el18rs | 3:522c6f850e91 | 2 | |
el18rs | 15:68114eae4053 | 3 | volatile int iH; |
el18rs | 22:403759d2f093 | 4 | volatile int iB; |
el18rs | 15:68114eae4053 | 5 | |
el18rs | 3:522c6f850e91 | 6 | TetrisGame::TetrisGame() |
el18rs | 3:522c6f850e91 | 7 | { |
el18rs | 15:68114eae4053 | 8 | |
el18rs | 3:522c6f850e91 | 9 | } |
el18rs | 3:522c6f850e91 | 10 | |
el18rs | 3:522c6f850e91 | 11 | TetrisGame::~TetrisGame() |
el18rs | 3:522c6f850e91 | 12 | { |
el18rs | 15:68114eae4053 | 13 | |
el18rs | 3:522c6f850e91 | 14 | } |
el18rs | 3:522c6f850e91 | 15 | |
el18rs | 11:0183a52c1077 | 16 | void TetrisGame::init(int speed) |
el18rs | 3:522c6f850e91 | 17 | { |
el18rs | 4:7ddd287a5d28 | 18 | // initialise game parameters |
el18rs | 11:0183a52c1077 | 19 | _px = 40; |
el18rs | 11:0183a52c1077 | 20 | _py = 4; |
el18rs | 9:58103274b2ab | 21 | _speed = speed; |
el18rs | 25:a7c89c54454a | 22 | score = 1; |
el18rs | 15:68114eae4053 | 23 | |
el18rs | 19:2ad31dbd5d11 | 24 | _tetromino.init(_px, _py); // puts tetromino in middle |
el18rs | 15:68114eae4053 | 25 | |
el18rs | 21:6d4dd906edde | 26 | // printf("initiate(%i)\n",_speed); |
el18rs | 15:68114eae4053 | 27 | |
el18rs | 3:522c6f850e91 | 28 | } |
el18rs | 3:522c6f850e91 | 29 | |
el18rs | 4:7ddd287a5d28 | 30 | |
el18rs | 22:403759d2f093 | 31 | void TetrisGame::read_input(Gamepad &pad) // read inputs |
el18rs | 3:522c6f850e91 | 32 | { |
el18rs | 3:522c6f850e91 | 33 | _d = pad.get_direction(); |
el18rs | 4:7ddd287a5d28 | 34 | _mag = pad.get_mag(); |
el18rs | 3:522c6f850e91 | 35 | } |
el18rs | 3:522c6f850e91 | 36 | |
el18rs | 21:6d4dd906edde | 37 | void TetrisGame::draw(N5110 &lcd) // draw elements in lcd buffer |
el18rs | 3:522c6f850e91 | 38 | { |
el18rs | 15:68114eae4053 | 39 | |
el18rs | 19:2ad31dbd5d11 | 40 | |
el18rs | 19:2ad31dbd5d11 | 41 | lcd.drawRect(19, 4, 42, HEIGHT - 4, FILL_TRANSPARENT); |
el18rs | 19:2ad31dbd5d11 | 42 | |
el18rs | 25:a7c89c54454a | 43 | print_scores(lcd); |
el18rs | 25:a7c89c54454a | 44 | |
el18rs | 6:39cbec524483 | 45 | _tetromino.draw(lcd); |
el18rs | 15:68114eae4053 | 46 | |
el18rs | 25:a7c89c54454a | 47 | |
el18rs | 23:cbfa9d1ee3db | 48 | |
el18rs | 19:2ad31dbd5d11 | 49 | // printf("draw (%i,%i)\n",_px,_py); |
el18rs | 15:68114eae4053 | 50 | |
el18rs | 3:522c6f850e91 | 51 | } |
el18rs | 3:522c6f850e91 | 52 | |
el18rs | 22:403759d2f093 | 53 | void TetrisGame::update(Gamepad &pad, N5110 &lcd) // update values |
el18rs | 3:522c6f850e91 | 54 | { |
el18rs | 15:68114eae4053 | 55 | |
el18rs | 4:7ddd287a5d28 | 56 | _tetromino.update(_d,_mag); |
el18rs | 15:68114eae4053 | 57 | |
el18rs | 25:a7c89c54454a | 58 | check_score(pad); |
el18rs | 25:a7c89c54454a | 59 | |
el18rs | 21:6d4dd906edde | 60 | check_wall_collision(pad, lcd); // check if block has collided with the floor |
el18rs | 21:6d4dd906edde | 61 | check_tetromino_collisions(pad, lcd); // check if block has collided with an old block |
el18rs | 15:68114eae4053 | 62 | |
el18rs | 19:2ad31dbd5d11 | 63 | // printf("update (%i,%i,%i)\n",_px,_py,_d); |
el18rs | 3:522c6f850e91 | 64 | } |
el18rs | 4:7ddd287a5d28 | 65 | |
el18rs | 4:7ddd287a5d28 | 66 | |
el18rs | 21:6d4dd906edde | 67 | void TetrisGame::check_wall_collision(Gamepad &pad, N5110 &lcd) // check if block has hit floor |
el18rs | 3:522c6f850e91 | 68 | { |
el18rs | 21:6d4dd906edde | 69 | Vector2D tetromino_pos = _tetromino.get_pos(); // get current positioning of block |
el18rs | 15:68114eae4053 | 70 | |
el18rs | 22:403759d2f093 | 71 | if (tetromino_pos.y + 4 >= (HEIGHT-1) ) { // if bottom of block is on bottom boundary |
el18rs | 15:68114eae4053 | 72 | |
el18rs | 21:6d4dd906edde | 73 | tetromino_pos.y = (HEIGHT-1) - 4; // stop block |
el18rs | 15:68114eae4053 | 74 | |
el18rs | 22:403759d2f093 | 75 | pad.tone(750.0,0.1); // play tone |
el18rs | 15:68114eae4053 | 76 | |
el18rs | 25:a7c89c54454a | 77 | score++; |
el18rs | 25:a7c89c54454a | 78 | |
el18rs | 22:403759d2f093 | 79 | cancel_line(lcd); // check if row is full |
el18rs | 15:68114eae4053 | 80 | |
el18rs | 15:68114eae4053 | 81 | _tetromino.init(_px, _py); // drop new shame |
el18rs | 19:2ad31dbd5d11 | 82 | |
el18rs | 21:6d4dd906edde | 83 | a = tetromino_pos.x; // save positions to be drawn on next screen |
el18rs | 13:600a34a047ca | 84 | b = tetromino_pos.y; |
el18rs | 15:68114eae4053 | 85 | |
el18rs | 21:6d4dd906edde | 86 | floor_hit_flag = 1; // set flag so program knows to draw block on next screen |
el18rs | 22:403759d2f093 | 87 | |
el18rs | 22:403759d2f093 | 88 | if (b <= 4) { // if pattern reaches top of screen |
el18rs | 22:403759d2f093 | 89 | exit_game(lcd); // game over |
el18rs | 20:ad685b35a1a4 | 90 | } |
el18rs | 15:68114eae4053 | 91 | |
el18rs | 23:cbfa9d1ee3db | 92 | // printf("floor hit!\n"); |
el18rs | 15:68114eae4053 | 93 | |
el18rs | 4:7ddd287a5d28 | 94 | } |
el18rs | 19:2ad31dbd5d11 | 95 | // printf("wall collision\n"); |
el18rs | 4:7ddd287a5d28 | 96 | } |
el18rs | 4:7ddd287a5d28 | 97 | |
el18rs | 22:403759d2f093 | 98 | void TetrisGame::check_tetromino_collisions(Gamepad &pad, N5110 &lcd) // check if block has old block beneath it |
el18rs | 5:53e021832adc | 99 | { |
el18rs | 21:6d4dd906edde | 100 | Vector2D tetromino_pos = _tetromino.get_pos(); // get current position of block |
el18rs | 5:53e021832adc | 101 | |
el18rs | 5:53e021832adc | 102 | if ( |
el18rs | 22:403759d2f093 | 103 | (lcd.getPixel(tetromino_pos.x, tetromino_pos.y + 4) == 1) || |
el18rs | 17:70d45e9e44a8 | 104 | (lcd.getPixel(tetromino_pos.x + 1, tetromino_pos.y + 4) == 1) || |
el18rs | 17:70d45e9e44a8 | 105 | (lcd.getPixel(tetromino_pos.x + 2, tetromino_pos.y + 4) == 1) || |
el18rs | 22:403759d2f093 | 106 | (lcd.getPixel(tetromino_pos.x + 3, tetromino_pos.y + 4) == 1) // if any of the 4 pixels directly below the block are black |
el18rs | 5:53e021832adc | 107 | ) { |
el18rs | 15:68114eae4053 | 108 | |
el18rs | 22:403759d2f093 | 109 | pad.tone(1000.0,0.1); // play tone |
el18rs | 25:a7c89c54454a | 110 | |
el18rs | 25:a7c89c54454a | 111 | score++; |
el18rs | 25:a7c89c54454a | 112 | |
el18rs | 21:6d4dd906edde | 113 | cancel_line(lcd); // check if row is full |
el18rs | 15:68114eae4053 | 114 | |
el18rs | 21:6d4dd906edde | 115 | _tetromino.init(_px, _py); // drop new block |
el18rs | 15:68114eae4053 | 116 | |
el18rs | 21:6d4dd906edde | 117 | a = tetromino_pos.x; // save positioning of old block |
el18rs | 16:fca1bbb06c44 | 118 | b = tetromino_pos.y; |
el18rs | 16:fca1bbb06c44 | 119 | |
el18rs | 21:6d4dd906edde | 120 | floor_hit_flag = 1; // set flag so program knows to draw block on next screen |
el18rs | 22:403759d2f093 | 121 | |
el18rs | 22:403759d2f093 | 122 | if (b <= 4) { // if pattern reaches top of screen |
el18rs | 22:403759d2f093 | 123 | exit_game(lcd); // game over |
el18rs | 20:ad685b35a1a4 | 124 | } |
el18rs | 15:68114eae4053 | 125 | |
el18rs | 23:cbfa9d1ee3db | 126 | // printf("blocks stacked!\n"); |
el18rs | 19:2ad31dbd5d11 | 127 | } |
el18rs | 19:2ad31dbd5d11 | 128 | // printf("tetromino collision\n"); |
el18rs | 5:53e021832adc | 129 | } |
el18rs | 6:39cbec524483 | 130 | |
el18rs | 22:403759d2f093 | 131 | void TetrisGame::cancel_line(N5110 &lcd) // check if row is full, if it is then delete line and drop pattern down |
el18rs | 6:39cbec524483 | 132 | { |
el18rs | 22:403759d2f093 | 133 | for(int j=4; j<=46; j++) { |
el18rs | 20:ad685b35a1a4 | 134 | for(int i=20; i<=60; i++) { |
el18rs | 21:6d4dd906edde | 135 | if (lcd.getPixel(i,j)==0) { // if the pixel is empty the counting stops and exits loop (row is not full) |
el18rs | 15:68114eae4053 | 136 | count=0; |
el18rs | 23:cbfa9d1ee3db | 137 | // printf("line not full\n"); |
el18rs | 15:68114eae4053 | 138 | break; |
el18rs | 22:403759d2f093 | 139 | } else if (lcd.getPixel(i,j)==1) { // if the pixel is full carries on counting |
el18rs | 15:68114eae4053 | 140 | count ++; |
el18rs | 23:cbfa9d1ee3db | 141 | // printf("counting... count=%i\n",count); |
el18rs | 6:39cbec524483 | 142 | } |
el18rs | 22:403759d2f093 | 143 | if (count==48) { // if gets to end of line |
el18rs | 22:403759d2f093 | 144 | count = 0; |
el18rs | 22:403759d2f093 | 145 | printf("line full\n"); |
el18rs | 22:403759d2f093 | 146 | // lcd.drawRect(20,j,40,4,FILL_WHITE); // clear line |
el18rs | 22:403759d2f093 | 147 | c = j; |
el18rs | 23:cbfa9d1ee3db | 148 | d = i; |
el18rs | 22:403759d2f093 | 149 | clear_line_flag = 1; |
el18rs | 22:403759d2f093 | 150 | floor_hit_flag = 0; |
el18rs | 23:cbfa9d1ee3db | 151 | // printf("line canceled!\n"); |
el18rs | 22:403759d2f093 | 152 | } |
el18rs | 6:39cbec524483 | 153 | } |
el18rs | 15:68114eae4053 | 154 | } |
el18rs | 23:cbfa9d1ee3db | 155 | // printf("cancel line\n"); |
el18rs | 15:68114eae4053 | 156 | } |
el18rs | 6:39cbec524483 | 157 | |
el18rs | 15:68114eae4053 | 158 | void TetrisGame::exit_game(N5110 &lcd) |
el18rs | 15:68114eae4053 | 159 | { |
el18rs | 15:68114eae4053 | 160 | lcd.clear(); |
el18rs | 23:cbfa9d1ee3db | 161 | lcd.printString(" GAME OVER \n",0, 3); |
el18rs | 15:68114eae4053 | 162 | lcd.refresh(); |
el18rs | 15:68114eae4053 | 163 | wait(10); |
el18rs | 23:cbfa9d1ee3db | 164 | // printf("game over!\n"); |
el18rs | 15:68114eae4053 | 165 | lcd.clear(); |
el18rs | 15:68114eae4053 | 166 | lcd.printString(" press RESET ",0,6); |
el18rs | 15:68114eae4053 | 167 | lcd.refresh(); |
el18rs | 23:cbfa9d1ee3db | 168 | // printf("press reset!\n"); |
el18rs | 15:68114eae4053 | 169 | exit(1.0); |
el18rs | 15:68114eae4053 | 170 | } |
el18rs | 15:68114eae4053 | 171 | |
el18rs | 15:68114eae4053 | 172 | void TetrisGame::fallenblocks(N5110 &lcd, int iH) |
el18rs | 15:68114eae4053 | 173 | { |
el18rs | 15:68114eae4053 | 174 | for (int i=0; i<=iH; i++) { |
el18rs | 15:68114eae4053 | 175 | x0 = X[i]; |
el18rs | 15:68114eae4053 | 176 | y0 = Y[i]; |
el18rs | 16:fca1bbb06c44 | 177 | lcd.drawRect(x0, y0, 4, 4, FILL_BLACK); |
el18rs | 19:2ad31dbd5d11 | 178 | // printf("block drawn\n"); |
el18rs | 15:68114eae4053 | 179 | } |
el18rs | 22:403759d2f093 | 180 | } |
el18rs | 22:403759d2f093 | 181 | |
el18rs | 23:cbfa9d1ee3db | 182 | void TetrisGame::currentscreen(N5110 &lcd) |
el18rs | 23:cbfa9d1ee3db | 183 | { |
el18rs | 23:cbfa9d1ee3db | 184 | for (int i=0; i<=83; i++) { |
el18rs | 23:cbfa9d1ee3db | 185 | for (int j=0; j<=47; j++) { |
el18rs | 23:cbfa9d1ee3db | 186 | if(lcd.getPixel(i,j)) { //if pixel is set |
el18rs | 23:cbfa9d1ee3db | 187 | buffer[i][j] = 1; |
el18rs | 23:cbfa9d1ee3db | 188 | } else { // pixel is clear |
el18rs | 23:cbfa9d1ee3db | 189 | buffer[i][j] = 0; |
el18rs | 23:cbfa9d1ee3db | 190 | } |
el18rs | 23:cbfa9d1ee3db | 191 | } |
el18rs | 23:cbfa9d1ee3db | 192 | } |
el18rs | 23:cbfa9d1ee3db | 193 | } |
el18rs | 23:cbfa9d1ee3db | 194 | |
el18rs | 23:cbfa9d1ee3db | 195 | void TetrisGame::clearline(N5110 &lcd, int iB) |
el18rs | 22:403759d2f093 | 196 | { |
el18rs | 22:403759d2f093 | 197 | for (int i=0; i<=iB; i++) { |
el18rs | 22:403759d2f093 | 198 | z0 = Z[i]; |
el18rs | 23:cbfa9d1ee3db | 199 | q0 = Q[i]; |
el18rs | 25:a7c89c54454a | 200 | lcd.drawRect(20, z0, 40, 4, FILL_WHITE); // clear rectagle over where the full row is |
el18rs | 25:a7c89c54454a | 201 | } |
el18rs | 25:a7c89c54454a | 202 | currentscreen(lcd); |
el18rs | 25:a7c89c54454a | 203 | for (int x=20; x<=60; x++) { |
el18rs | 25:a7c89c54454a | 204 | for (int y=c; y>=0; y--) { // screen above row that was removed |
el18rs | 25:a7c89c54454a | 205 | if (buffer[x][y]) { // buffer of screen |
el18rs | 25:a7c89c54454a | 206 | lcd.setPixel(x,y, false); // remove pixel |
el18rs | 25:a7c89c54454a | 207 | lcd.setPixel(x,y+4); // replace with pixel above it |
el18rs | 25:a7c89c54454a | 208 | } |
el18rs | 25:a7c89c54454a | 209 | } |
el18rs | 22:403759d2f093 | 210 | } |
el18rs | 23:cbfa9d1ee3db | 211 | } |
el18rs | 23:cbfa9d1ee3db | 212 | |
el18rs | 25:a7c89c54454a | 213 | void TetrisGame::print_scores(N5110 &lcd) // print score on screen |
el18rs | 23:cbfa9d1ee3db | 214 | { |
el18rs | 25:a7c89c54454a | 215 | char Sbuffer[14]; |
el18rs | 25:a7c89c54454a | 216 | int n, _score = score; |
el18rs | 25:a7c89c54454a | 217 | n=sprintf (Sbuffer, "%d",_score); |
el18rs | 25:a7c89c54454a | 218 | // printf ("[%s] is a string %d chars long\n",Sbuffer,n); |
el18rs | 25:a7c89c54454a | 219 | lcd.printString(Sbuffer,65,3); |
el18rs | 23:cbfa9d1ee3db | 220 | } |
el18rs | 23:cbfa9d1ee3db | 221 | |
el18rs | 25:a7c89c54454a | 222 | void TetrisGame::check_score(Gamepad &pad) // update scores |
el18rs | 23:cbfa9d1ee3db | 223 | { |
el18rs | 23:cbfa9d1ee3db | 224 | if ( clear_line_flag == 1) { |
el18rs | 25:a7c89c54454a | 225 | score+=10; |
el18rs | 23:cbfa9d1ee3db | 226 | } |
el18rs | 15:68114eae4053 | 227 | } |