Tetris game for mbed.
Dependencies: 4DGL-uLCD-SE SDFileSystem mbed-rtos mbed wave_player
Fork of HelloWorld by
tetris.cpp@2:36cda8980746, 2016-11-07 (annotated)
- Committer:
- greiner218
- Date:
- Mon Nov 07 00:43:45 2016 +0000
- Revision:
- 2:36cda8980746
V1
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
greiner218 | 2:36cda8980746 | 1 | #include <stdlib.h> |
greiner218 | 2:36cda8980746 | 2 | #include <time.h> |
greiner218 | 2:36cda8980746 | 3 | #include "tetris.h" |
greiner218 | 2:36cda8980746 | 4 | #include "uLCD_4DGL.h" |
greiner218 | 2:36cda8980746 | 5 | #include "rtos.h" |
greiner218 | 2:36cda8980746 | 6 | #include "mbed.h" |
greiner218 | 2:36cda8980746 | 7 | |
greiner218 | 2:36cda8980746 | 8 | uLCD_4DGL uLCD(p28,p27,p29); // serial tx, serial rx, reset pin; |
greiner218 | 2:36cda8980746 | 9 | Mutex lcd_mutex; |
greiner218 | 2:36cda8980746 | 10 | |
greiner218 | 2:36cda8980746 | 11 | Block::Block(){ |
greiner218 | 2:36cda8980746 | 12 | srand(time(NULL)); |
greiner218 | 2:36cda8980746 | 13 | block = block_list[rand() % SET_SIZE]; |
greiner218 | 2:36cda8980746 | 14 | offset = DIMX / 2; |
greiner218 | 2:36cda8980746 | 15 | height = DIMZ - 5; |
greiner218 | 2:36cda8980746 | 16 | } |
greiner218 | 2:36cda8980746 | 17 | |
greiner218 | 2:36cda8980746 | 18 | Block::Block(short ind){ |
greiner218 | 2:36cda8980746 | 19 | block = block_list[ind]; |
greiner218 | 2:36cda8980746 | 20 | offset = DIMX / 2; |
greiner218 | 2:36cda8980746 | 21 | height = DIMZ - 5; |
greiner218 | 2:36cda8980746 | 22 | } |
greiner218 | 2:36cda8980746 | 23 | |
greiner218 | 2:36cda8980746 | 24 | Block::Block(short ind, short offs, short h){ |
greiner218 | 2:36cda8980746 | 25 | block = block_list[ind]; |
greiner218 | 2:36cda8980746 | 26 | offset = offs; |
greiner218 | 2:36cda8980746 | 27 | height = h; |
greiner218 | 2:36cda8980746 | 28 | } |
greiner218 | 2:36cda8980746 | 29 | |
greiner218 | 2:36cda8980746 | 30 | unsigned long long Block::getFace(int n){ |
greiner218 | 2:36cda8980746 | 31 | unsigned long long rv = 0; |
greiner218 | 2:36cda8980746 | 32 | unsigned int lower = block&0xFFFFFFFFULL; |
greiner218 | 2:36cda8980746 | 33 | unsigned int upper = (block>>32); |
greiner218 | 2:36cda8980746 | 34 | switch(n){ |
greiner218 | 2:36cda8980746 | 35 | case 0: |
greiner218 | 2:36cda8980746 | 36 | rv = lower&FACE0; |
greiner218 | 2:36cda8980746 | 37 | break; |
greiner218 | 2:36cda8980746 | 38 | case 1: |
greiner218 | 2:36cda8980746 | 39 | rv = (lower>>16)&FACE0;//shift(block,-16)&FACE0; |
greiner218 | 2:36cda8980746 | 40 | break; |
greiner218 | 2:36cda8980746 | 41 | case 2: |
greiner218 | 2:36cda8980746 | 42 | rv = (upper)&FACE0;//shift(block,-16)&FACE0; |
greiner218 | 2:36cda8980746 | 43 | break; |
greiner218 | 2:36cda8980746 | 44 | case 3: |
greiner218 | 2:36cda8980746 | 45 | rv = (upper>>16)&FACE0;//shift(block,-16)&FACE0; |
greiner218 | 2:36cda8980746 | 46 | break; |
greiner218 | 2:36cda8980746 | 47 | default: |
greiner218 | 2:36cda8980746 | 48 | rv = 0; |
greiner218 | 2:36cda8980746 | 49 | } |
greiner218 | 2:36cda8980746 | 50 | return rv; |
greiner218 | 2:36cda8980746 | 51 | |
greiner218 | 2:36cda8980746 | 52 | } |
greiner218 | 2:36cda8980746 | 53 | |
greiner218 | 2:36cda8980746 | 54 | unsigned long long Block::getLine(int n){ |
greiner218 | 2:36cda8980746 | 55 | unsigned long long rv = 0; |
greiner218 | 2:36cda8980746 | 56 | unsigned int lower = block&0xFFFFFFFFULL; |
greiner218 | 2:36cda8980746 | 57 | unsigned int upper = (block>>32); |
greiner218 | 2:36cda8980746 | 58 | switch(n){ |
greiner218 | 2:36cda8980746 | 59 | case 0: |
greiner218 | 2:36cda8980746 | 60 | rv = (lower&LINE0) | ((upper&LINE0)<<32); |
greiner218 | 2:36cda8980746 | 61 | break; |
greiner218 | 2:36cda8980746 | 62 | case 1: |
greiner218 | 2:36cda8980746 | 63 | lower = lower >>4; |
greiner218 | 2:36cda8980746 | 64 | upper = upper >>4; |
greiner218 | 2:36cda8980746 | 65 | rv = (lower&LINE0) | ((upper&LINE0)<<32); |
greiner218 | 2:36cda8980746 | 66 | break; |
greiner218 | 2:36cda8980746 | 67 | case 2: |
greiner218 | 2:36cda8980746 | 68 | lower = lower >>8; |
greiner218 | 2:36cda8980746 | 69 | upper = upper >>8; |
greiner218 | 2:36cda8980746 | 70 | rv = (lower&LINE0) | ((upper&LINE0)<<32); |
greiner218 | 2:36cda8980746 | 71 | break; |
greiner218 | 2:36cda8980746 | 72 | case 3: |
greiner218 | 2:36cda8980746 | 73 | lower = lower >>12; |
greiner218 | 2:36cda8980746 | 74 | upper = upper >>12; |
greiner218 | 2:36cda8980746 | 75 | rv = (lower&LINE0) | ((upper&LINE0)<<32); |
greiner218 | 2:36cda8980746 | 76 | break; |
greiner218 | 2:36cda8980746 | 77 | default: |
greiner218 | 2:36cda8980746 | 78 | rv = 0; |
greiner218 | 2:36cda8980746 | 79 | } |
greiner218 | 2:36cda8980746 | 80 | return rv; |
greiner218 | 2:36cda8980746 | 81 | |
greiner218 | 2:36cda8980746 | 82 | |
greiner218 | 2:36cda8980746 | 83 | } |
greiner218 | 2:36cda8980746 | 84 | |
greiner218 | 2:36cda8980746 | 85 | unsigned long long Block::getFaceLine(int f, int l){ |
greiner218 | 2:36cda8980746 | 86 | unsigned long long face = getFace(f); |
greiner218 | 2:36cda8980746 | 87 | unsigned long long rv = 0; |
greiner218 | 2:36cda8980746 | 88 | switch(l){ |
greiner218 | 2:36cda8980746 | 89 | case 0: |
greiner218 | 2:36cda8980746 | 90 | rv = (face&0x000F); |
greiner218 | 2:36cda8980746 | 91 | break; |
greiner218 | 2:36cda8980746 | 92 | case 1: |
greiner218 | 2:36cda8980746 | 93 | rv = (face&0x00F0)>>4; |
greiner218 | 2:36cda8980746 | 94 | break; |
greiner218 | 2:36cda8980746 | 95 | case 2: |
greiner218 | 2:36cda8980746 | 96 | rv = (face&0x0F00)>>8; |
greiner218 | 2:36cda8980746 | 97 | break; |
greiner218 | 2:36cda8980746 | 98 | case 3: |
greiner218 | 2:36cda8980746 | 99 | rv = (face&0xF000)>>12; |
greiner218 | 2:36cda8980746 | 100 | break; |
greiner218 | 2:36cda8980746 | 101 | default: |
greiner218 | 2:36cda8980746 | 102 | rv = 0; |
greiner218 | 2:36cda8980746 | 103 | } |
greiner218 | 2:36cda8980746 | 104 | return rv; |
greiner218 | 2:36cda8980746 | 105 | } |
greiner218 | 2:36cda8980746 | 106 | void Block::rotY(){ |
greiner218 | 2:36cda8980746 | 107 | unsigned long long temp = block; |
greiner218 | 2:36cda8980746 | 108 | block = ((temp&0x0001000100010001ULL)<<3)|((temp&0x0002000200020002ULL)<<6)| |
greiner218 | 2:36cda8980746 | 109 | ((temp&0x0004000400040004ULL)<<9)|((temp&0x0008000800080008ULL)<<12)| |
greiner218 | 2:36cda8980746 | 110 | ((temp&0x0010001000100010ULL)>>2)|((temp&0x0020002000200020ULL)<<1)| |
greiner218 | 2:36cda8980746 | 111 | ((temp&0x0040004000400040ULL)<<4)|((temp&0x0080008000800080ULL)<<7)| |
greiner218 | 2:36cda8980746 | 112 | ((temp&0x0100010001000100ULL)>>7)|((temp&0x0200020002000200ULL)>>4)| |
greiner218 | 2:36cda8980746 | 113 | ((temp&0x0400040004000400ULL)>>1)|((temp&0x0800080008000800ULL)<<2)| |
greiner218 | 2:36cda8980746 | 114 | ((temp&0x1000100010001000ULL)>>12)|((temp&0x2000200020002000ULL)>>9)| |
greiner218 | 2:36cda8980746 | 115 | ((temp&0x4000400040004000ULL)>>6)|((temp&0x8000800080008000ULL)>>3); |
greiner218 | 2:36cda8980746 | 116 | } |
greiner218 | 2:36cda8980746 | 117 | void Block::rotZ(){ |
greiner218 | 2:36cda8980746 | 118 | unsigned long long temp = block; |
greiner218 | 2:36cda8980746 | 119 | block = ((temp&0x0000000000001111ULL)<<3) |((temp&0x0000000000002222ULL)<<18)| |
greiner218 | 2:36cda8980746 | 120 | ((temp&0x0000000000004444ULL)<<33)|((temp&0x0000000000008888ULL)<<48)| |
greiner218 | 2:36cda8980746 | 121 | ((temp&0x0000000011110000ULL)>>14)|((temp&0x0000000022220000ULL)<<1) | |
greiner218 | 2:36cda8980746 | 122 | ((temp&0x0000000044440000ULL)<<16)|((temp&0x0000000088880000ULL)<<31)| |
greiner218 | 2:36cda8980746 | 123 | ((temp&0x0000111100000000ULL)>>31)|((temp&0x0000222200000000ULL)>>16)| |
greiner218 | 2:36cda8980746 | 124 | ((temp&0x0000444400000000ULL)>>1) |((temp&0x0000888800000000ULL)<<14)| |
greiner218 | 2:36cda8980746 | 125 | ((temp&0x1111000000000000ULL)>>48)|((temp&0x2222000000000000ULL)>>33)| |
greiner218 | 2:36cda8980746 | 126 | ((temp&0x4444000000000000ULL)>>18)|((temp&0x8888000000000000ULL)>>3); |
greiner218 | 2:36cda8980746 | 127 | } |
greiner218 | 2:36cda8980746 | 128 | void Block::rotX(){ |
greiner218 | 2:36cda8980746 | 129 | unsigned long long temp = block; |
greiner218 | 2:36cda8980746 | 130 | block = ((temp&0x000000000000000FULL)<<12)|((temp&0x00000000000000F0ULL)<<24)| |
greiner218 | 2:36cda8980746 | 131 | ((temp&0x0000000000000F00ULL)<<36)|((temp&0x000000000000F000ULL)<<48)| |
greiner218 | 2:36cda8980746 | 132 | ((temp&0x00000000000F0000ULL)>>8)| ((temp&0x0000000000F00000ULL)<<4)| |
greiner218 | 2:36cda8980746 | 133 | ((temp&0x000000000F000000ULL)<<16)|((temp&0x00000000F0000000ULL)<<28)| |
greiner218 | 2:36cda8980746 | 134 | ((temp&0x0000000F00000000ULL)>>28)|((temp&0x000000F000000000ULL)>>16)| |
greiner218 | 2:36cda8980746 | 135 | ((temp&0x00000F0000000000ULL)>>4) |((temp&0x0000F00000000000ULL)<<8)| |
greiner218 | 2:36cda8980746 | 136 | ((temp&0x000F000000000000ULL)>>48)|((temp&0x00F0000000000000ULL)>>36)| |
greiner218 | 2:36cda8980746 | 137 | ((temp&0x0F00000000000000ULL)>>24)|((temp&0xF000000000000000ULL)>>12); |
greiner218 | 2:36cda8980746 | 138 | } |
greiner218 | 2:36cda8980746 | 139 | void Block::movR(){ |
greiner218 | 2:36cda8980746 | 140 | offset++; |
greiner218 | 2:36cda8980746 | 141 | //if (offset >= DIMX) offset = 0; |
greiner218 | 2:36cda8980746 | 142 | } |
greiner218 | 2:36cda8980746 | 143 | |
greiner218 | 2:36cda8980746 | 144 | void Block::movL(){ |
greiner218 | 2:36cda8980746 | 145 | offset--; |
greiner218 | 2:36cda8980746 | 146 | if (offset <-3) offset = -3; |
greiner218 | 2:36cda8980746 | 147 | } |
greiner218 | 2:36cda8980746 | 148 | |
greiner218 | 2:36cda8980746 | 149 | void Block::movB(){ |
greiner218 | 2:36cda8980746 | 150 | unsigned long long temp = block; |
greiner218 | 2:36cda8980746 | 151 | block = ((temp&0x0000FFFFFFFFFFFFULL)<<16)|((temp&0xFFFF000000000000ULL)>>48); |
greiner218 | 2:36cda8980746 | 152 | } |
greiner218 | 2:36cda8980746 | 153 | |
greiner218 | 2:36cda8980746 | 154 | void Block::movF(){ |
greiner218 | 2:36cda8980746 | 155 | unsigned long long temp = block; |
greiner218 | 2:36cda8980746 | 156 | block = ((temp&0xFFFFFFFFFFFF0000ULL)>>16)|((temp&0x000000000000FFFFULL)<<48); |
greiner218 | 2:36cda8980746 | 157 | } |
greiner218 | 2:36cda8980746 | 158 | |
greiner218 | 2:36cda8980746 | 159 | void Block::movU(){ |
greiner218 | 2:36cda8980746 | 160 | height++; |
greiner218 | 2:36cda8980746 | 161 | } |
greiner218 | 2:36cda8980746 | 162 | |
greiner218 | 2:36cda8980746 | 163 | void Block::movD(){ |
greiner218 | 2:36cda8980746 | 164 | height--; |
greiner218 | 2:36cda8980746 | 165 | //if (height<-3) height = -3; |
greiner218 | 2:36cda8980746 | 166 | } |
greiner218 | 2:36cda8980746 | 167 | |
greiner218 | 2:36cda8980746 | 168 | |
greiner218 | 2:36cda8980746 | 169 | |
greiner218 | 2:36cda8980746 | 170 | Board::Board(){ |
greiner218 | 2:36cda8980746 | 171 | nextBlock.offset = activeBlock.offset; |
greiner218 | 2:36cda8980746 | 172 | nextBlock.height = activeBlock.height; |
greiner218 | 2:36cda8980746 | 173 | nextBlock.block = activeBlock.block; |
greiner218 | 2:36cda8980746 | 174 | int i; |
greiner218 | 2:36cda8980746 | 175 | for (i = 0; i<4; i++) line[i] = 0xFFFFFFFFFFFFFFFFULL; |
greiner218 | 2:36cda8980746 | 176 | for (i = 4; i<DIMZ+4; i++) line[i] = 0xF807F807F807F807ULL; |
greiner218 | 2:36cda8980746 | 177 | score = 0; |
greiner218 | 2:36cda8980746 | 178 | } |
greiner218 | 2:36cda8980746 | 179 | |
greiner218 | 2:36cda8980746 | 180 | int Board::check(){ |
greiner218 | 2:36cda8980746 | 181 | //Check next block with board lines. |
greiner218 | 2:36cda8980746 | 182 | //Returns 0 when a collision (illegal state) is detected. |
greiner218 | 2:36cda8980746 | 183 | //Returns 1 when move is legal. |
greiner218 | 2:36cda8980746 | 184 | int invalid = 0; |
greiner218 | 2:36cda8980746 | 185 | int f = 0; |
greiner218 | 2:36cda8980746 | 186 | int l = 0; |
greiner218 | 2:36cda8980746 | 187 | if (nextBlock.height >-4){ |
greiner218 | 2:36cda8980746 | 188 | for (l=0;l<4;l++){ |
greiner218 | 2:36cda8980746 | 189 | for (f=0;f<4;f++){ |
greiner218 | 2:36cda8980746 | 190 | if (!checkFaceLine(f,l)) invalid = 1; |
greiner218 | 2:36cda8980746 | 191 | } |
greiner218 | 2:36cda8980746 | 192 | } |
greiner218 | 2:36cda8980746 | 193 | } else{ |
greiner218 | 2:36cda8980746 | 194 | invalid = 1; |
greiner218 | 2:36cda8980746 | 195 | } |
greiner218 | 2:36cda8980746 | 196 | if(invalid){ |
greiner218 | 2:36cda8980746 | 197 | nextBlock.height = activeBlock.height; |
greiner218 | 2:36cda8980746 | 198 | nextBlock.offset = activeBlock.offset; |
greiner218 | 2:36cda8980746 | 199 | nextBlock.block = activeBlock.block; |
greiner218 | 2:36cda8980746 | 200 | return 0; |
greiner218 | 2:36cda8980746 | 201 | } |
greiner218 | 2:36cda8980746 | 202 | return 1; |
greiner218 | 2:36cda8980746 | 203 | } |
greiner218 | 2:36cda8980746 | 204 | |
greiner218 | 2:36cda8980746 | 205 | int Board::checkFaceLine(int f, int l){ |
greiner218 | 2:36cda8980746 | 206 | //Determine which board line is being checked |
greiner218 | 2:36cda8980746 | 207 | unsigned long long boardLine = line[nextBlock.height + l +4]; |
greiner218 | 2:36cda8980746 | 208 | unsigned long long val = nextBlock.getFaceLine(f,l); |
greiner218 | 2:36cda8980746 | 209 | //Determine which board values are being compared |
greiner218 | 2:36cda8980746 | 210 | unsigned int lower = boardLine&0x00000000FFFFFFFF; |
greiner218 | 2:36cda8980746 | 211 | unsigned int upper = boardLine >> 32; |
greiner218 | 2:36cda8980746 | 212 | switch(f){ |
greiner218 | 2:36cda8980746 | 213 | case 0: |
greiner218 | 2:36cda8980746 | 214 | boardLine = lower&0x0000FFFF; |
greiner218 | 2:36cda8980746 | 215 | break; |
greiner218 | 2:36cda8980746 | 216 | case 1: |
greiner218 | 2:36cda8980746 | 217 | boardLine = lower>>16; |
greiner218 | 2:36cda8980746 | 218 | break; |
greiner218 | 2:36cda8980746 | 219 | case 2: |
greiner218 | 2:36cda8980746 | 220 | boardLine = upper&0x0000FFFF; |
greiner218 | 2:36cda8980746 | 221 | break; |
greiner218 | 2:36cda8980746 | 222 | case 3: |
greiner218 | 2:36cda8980746 | 223 | boardLine = upper>>16; |
greiner218 | 2:36cda8980746 | 224 | break; |
greiner218 | 2:36cda8980746 | 225 | default: |
greiner218 | 2:36cda8980746 | 226 | break; |
greiner218 | 2:36cda8980746 | 227 | } |
greiner218 | 2:36cda8980746 | 228 | //Shift block to align with board |
greiner218 | 2:36cda8980746 | 229 | val = shift(val,3+nextBlock.offset); |
greiner218 | 2:36cda8980746 | 230 | //boardLine = (boardLine>>2)<<nextBlock.offset; |
greiner218 | 2:36cda8980746 | 231 | //Compare block line value with the board value |
greiner218 | 2:36cda8980746 | 232 | if(boardLine&val)return 0;//Collision detected |
greiner218 | 2:36cda8980746 | 233 | return 1; |
greiner218 | 2:36cda8980746 | 234 | |
greiner218 | 2:36cda8980746 | 235 | } |
greiner218 | 2:36cda8980746 | 236 | |
greiner218 | 2:36cda8980746 | 237 | void Board::updateBlock(){ |
greiner218 | 2:36cda8980746 | 238 | eraseBlock(activeBlock); |
greiner218 | 2:36cda8980746 | 239 | activeBlock = nextBlock; |
greiner218 | 2:36cda8980746 | 240 | drawBlock(activeBlock); |
greiner218 | 2:36cda8980746 | 241 | } |
greiner218 | 2:36cda8980746 | 242 | |
greiner218 | 2:36cda8980746 | 243 | void Board::checkAndUpdate(){ |
greiner218 | 2:36cda8980746 | 244 | if(check()) updateBlock(); |
greiner218 | 2:36cda8980746 | 245 | } |
greiner218 | 2:36cda8980746 | 246 | |
greiner218 | 2:36cda8980746 | 247 | void Board::setBlock(){ |
greiner218 | 2:36cda8980746 | 248 | //Set block line by line. |
greiner218 | 2:36cda8980746 | 249 | int f = 0; |
greiner218 | 2:36cda8980746 | 250 | int l = 0; |
greiner218 | 2:36cda8980746 | 251 | for (f=0; f<4; f++){ |
greiner218 | 2:36cda8980746 | 252 | for (l=0; l<4; l++){ |
greiner218 | 2:36cda8980746 | 253 | setBlockFaceLine(f,l); |
greiner218 | 2:36cda8980746 | 254 | } |
greiner218 | 2:36cda8980746 | 255 | } |
greiner218 | 2:36cda8980746 | 256 | //Now check if lines need to be cleared |
greiner218 | 2:36cda8980746 | 257 | for (l=activeBlock.height+3; (l>activeBlock.height-1); l--){ |
greiner218 | 2:36cda8980746 | 258 | checkForClear(l+4); |
greiner218 | 2:36cda8980746 | 259 | } |
greiner218 | 2:36cda8980746 | 260 | //Now check if you lost |
greiner218 | 2:36cda8980746 | 261 | checkLose(); |
greiner218 | 2:36cda8980746 | 262 | } |
greiner218 | 2:36cda8980746 | 263 | |
greiner218 | 2:36cda8980746 | 264 | void Board::checkForClear(int l){ |
greiner218 | 2:36cda8980746 | 265 | if(l>3){ |
greiner218 | 2:36cda8980746 | 266 | if( line[l] == 0xFFFFFFFFFFFFFFFFULL) clearLine(l); |
greiner218 | 2:36cda8980746 | 267 | } |
greiner218 | 2:36cda8980746 | 268 | } |
greiner218 | 2:36cda8980746 | 269 | |
greiner218 | 2:36cda8980746 | 270 | void Board::setBlockFaceLine(int f, int l){ |
greiner218 | 2:36cda8980746 | 271 | //Determine which board line is being set |
greiner218 | 2:36cda8980746 | 272 | unsigned long long boardLine = getFaceLine(f,l+4+nextBlock.height); |
greiner218 | 2:36cda8980746 | 273 | unsigned long long val = nextBlock.getFaceLine(f,l); |
greiner218 | 2:36cda8980746 | 274 | //Shift block to align with board |
greiner218 | 2:36cda8980746 | 275 | val = shift(val,3+nextBlock.offset); |
greiner218 | 2:36cda8980746 | 276 | //Write to the board |
greiner218 | 2:36cda8980746 | 277 | boardLine |= val; |
greiner218 | 2:36cda8980746 | 278 | setBlockFaceLineVal(f,l+4+nextBlock.height, boardLine); |
greiner218 | 2:36cda8980746 | 279 | } |
greiner218 | 2:36cda8980746 | 280 | |
greiner218 | 2:36cda8980746 | 281 | void Board::setBlockFaceLineVal(int f, int l, unsigned long long bl){ |
greiner218 | 2:36cda8980746 | 282 | switch(f){ |
greiner218 | 2:36cda8980746 | 283 | case 0: |
greiner218 | 2:36cda8980746 | 284 | line[l] |= (bl); |
greiner218 | 2:36cda8980746 | 285 | break; |
greiner218 | 2:36cda8980746 | 286 | case 1: |
greiner218 | 2:36cda8980746 | 287 | line[l] |= (bl<<16); |
greiner218 | 2:36cda8980746 | 288 | break; |
greiner218 | 2:36cda8980746 | 289 | case 2: |
greiner218 | 2:36cda8980746 | 290 | line[l] |= (bl<<32); |
greiner218 | 2:36cda8980746 | 291 | break; |
greiner218 | 2:36cda8980746 | 292 | case 3: |
greiner218 | 2:36cda8980746 | 293 | line[l] |= (bl<<48); |
greiner218 | 2:36cda8980746 | 294 | break; |
greiner218 | 2:36cda8980746 | 295 | default: |
greiner218 | 2:36cda8980746 | 296 | break; |
greiner218 | 2:36cda8980746 | 297 | } |
greiner218 | 2:36cda8980746 | 298 | } |
greiner218 | 2:36cda8980746 | 299 | |
greiner218 | 2:36cda8980746 | 300 | void Board::drawGrid(){ |
greiner218 | 2:36cda8980746 | 301 | uLCD.baudrate(3000000); |
greiner218 | 2:36cda8980746 | 302 | int col = BLUE; |
greiner218 | 2:36cda8980746 | 303 | if(lost) col = RED; |
greiner218 | 2:36cda8980746 | 304 | lcd_mutex.lock(); |
greiner218 | 2:36cda8980746 | 305 | //Top left |
greiner218 | 2:36cda8980746 | 306 | uLCD.rectangle(127,0,126,91,col); |
greiner218 | 2:36cda8980746 | 307 | uLCD.rectangle(93,0,92,91,col); |
greiner218 | 2:36cda8980746 | 308 | //Bot right |
greiner218 | 2:36cda8980746 | 309 | uLCD.rectangle(0,127,1,36,col); |
greiner218 | 2:36cda8980746 | 310 | uLCD.rectangle(34,127,35,36,col); |
greiner218 | 2:36cda8980746 | 311 | //Bot left |
greiner218 | 2:36cda8980746 | 312 | uLCD.rectangle(0,0,93,1,col); |
greiner218 | 2:36cda8980746 | 313 | uLCD.rectangle(0,34,93,35,col); |
greiner218 | 2:36cda8980746 | 314 | //Top right |
greiner218 | 2:36cda8980746 | 315 | uLCD.rectangle(127,127,34,126,col); |
greiner218 | 2:36cda8980746 | 316 | uLCD.rectangle(127,93,34,92,col); |
greiner218 | 2:36cda8980746 | 317 | |
greiner218 | 2:36cda8980746 | 318 | drawBlock(activeBlock); |
greiner218 | 2:36cda8980746 | 319 | drawScore(); |
greiner218 | 2:36cda8980746 | 320 | lcd_mutex.unlock(); |
greiner218 | 2:36cda8980746 | 321 | } |
greiner218 | 2:36cda8980746 | 322 | void Board::drawPix(int line, int offset, int grid){ |
greiner218 | 2:36cda8980746 | 323 | int x0; |
greiner218 | 2:36cda8980746 | 324 | int y0; |
greiner218 | 2:36cda8980746 | 325 | switch(grid){ |
greiner218 | 2:36cda8980746 | 326 | case 0: |
greiner218 | 2:36cda8980746 | 327 | x0 = 94; |
greiner218 | 2:36cda8980746 | 328 | y0 = 36; |
greiner218 | 2:36cda8980746 | 329 | uLCD.rectangle(y0 + 4*line, x0 + 4*offset, y0 + 4*line + 3, x0 + 4*offset + 3, RED); |
greiner218 | 2:36cda8980746 | 330 | break; |
greiner218 | 2:36cda8980746 | 331 | case 1: |
greiner218 | 2:36cda8980746 | 332 | x0 = 36; |
greiner218 | 2:36cda8980746 | 333 | y0 = 33; |
greiner218 | 2:36cda8980746 | 334 | uLCD.rectangle(y0 - 4*offset, x0 + 4*line, y0 - 4*offset - 3, x0 + 4*line + 3, RED); |
greiner218 | 2:36cda8980746 | 335 | break; |
greiner218 | 2:36cda8980746 | 336 | case 2: |
greiner218 | 2:36cda8980746 | 337 | x0 = 33; |
greiner218 | 2:36cda8980746 | 338 | y0 = 91; |
greiner218 | 2:36cda8980746 | 339 | uLCD.rectangle(y0 - 4*line, x0 - 4*offset, y0 - 4*line - 3, x0 - 4*offset - 3, RED); |
greiner218 | 2:36cda8980746 | 340 | break; |
greiner218 | 2:36cda8980746 | 341 | case 3: |
greiner218 | 2:36cda8980746 | 342 | x0 = 91; |
greiner218 | 2:36cda8980746 | 343 | y0 = 94; |
greiner218 | 2:36cda8980746 | 344 | uLCD.rectangle(y0 + 4*offset, x0 - 4*line, y0 + 4*offset + 3, x0 - 4*line - 3, RED); |
greiner218 | 2:36cda8980746 | 345 | break; |
greiner218 | 2:36cda8980746 | 346 | default: |
greiner218 | 2:36cda8980746 | 347 | break; |
greiner218 | 2:36cda8980746 | 348 | |
greiner218 | 2:36cda8980746 | 349 | } |
greiner218 | 2:36cda8980746 | 350 | |
greiner218 | 2:36cda8980746 | 351 | } |
greiner218 | 2:36cda8980746 | 352 | void Board::erasePix(int line, int offset, int grid){ |
greiner218 | 2:36cda8980746 | 353 | int x0; |
greiner218 | 2:36cda8980746 | 354 | int y0; |
greiner218 | 2:36cda8980746 | 355 | switch(grid){ |
greiner218 | 2:36cda8980746 | 356 | case 0: |
greiner218 | 2:36cda8980746 | 357 | x0 = 94; |
greiner218 | 2:36cda8980746 | 358 | y0 = 36; |
greiner218 | 2:36cda8980746 | 359 | uLCD.rectangle(y0 + 4*line, x0 + 4*offset, y0 + 4*line + 3, x0 + 4*offset + 3, BLACK); |
greiner218 | 2:36cda8980746 | 360 | break; |
greiner218 | 2:36cda8980746 | 361 | case 1: |
greiner218 | 2:36cda8980746 | 362 | x0 = 36; |
greiner218 | 2:36cda8980746 | 363 | y0 = 33; |
greiner218 | 2:36cda8980746 | 364 | uLCD.rectangle(y0 - 4*offset, x0 + 4*line, y0 - 4*offset - 3, x0 + 4*line + 3, BLACK); |
greiner218 | 2:36cda8980746 | 365 | break; |
greiner218 | 2:36cda8980746 | 366 | case 2: |
greiner218 | 2:36cda8980746 | 367 | x0 = 33; |
greiner218 | 2:36cda8980746 | 368 | y0 = 91; |
greiner218 | 2:36cda8980746 | 369 | uLCD.rectangle(y0 - 4*line, x0 - 4*offset, y0 - 4*line - 3, x0 - 4*offset - 3, BLACK); |
greiner218 | 2:36cda8980746 | 370 | break; |
greiner218 | 2:36cda8980746 | 371 | case 3: |
greiner218 | 2:36cda8980746 | 372 | x0 = 91; |
greiner218 | 2:36cda8980746 | 373 | y0 = 94; |
greiner218 | 2:36cda8980746 | 374 | uLCD.rectangle(y0 + 4*offset, x0 - 4*line, y0 + 4*offset + 3, x0 - 4*line - 3, BLACK); |
greiner218 | 2:36cda8980746 | 375 | break; |
greiner218 | 2:36cda8980746 | 376 | default: |
greiner218 | 2:36cda8980746 | 377 | break; |
greiner218 | 2:36cda8980746 | 378 | |
greiner218 | 2:36cda8980746 | 379 | } |
greiner218 | 2:36cda8980746 | 380 | |
greiner218 | 2:36cda8980746 | 381 | } |
greiner218 | 2:36cda8980746 | 382 | |
greiner218 | 2:36cda8980746 | 383 | |
greiner218 | 2:36cda8980746 | 384 | void Board::drawBlock(Block blk){ |
greiner218 | 2:36cda8980746 | 385 | unsigned long long temp; |
greiner218 | 2:36cda8980746 | 386 | int i = 0; |
greiner218 | 2:36cda8980746 | 387 | lcd_mutex.lock(); |
greiner218 | 2:36cda8980746 | 388 | //Draw front face in grid 0 |
greiner218 | 2:36cda8980746 | 389 | temp = (blk.block&FACE0); |
greiner218 | 2:36cda8980746 | 390 | for (i=0; i<16; i++){ |
greiner218 | 2:36cda8980746 | 391 | if(temp&(0x01<<i)) drawPix(blk.height+(i/4), blk.offset+(i%4),0); |
greiner218 | 2:36cda8980746 | 392 | } |
greiner218 | 2:36cda8980746 | 393 | //Draw second face in grid 1 |
greiner218 | 2:36cda8980746 | 394 | temp = (blk.block&FACE1)>>16; |
greiner218 | 2:36cda8980746 | 395 | for (i=0; i<16; i++){ |
greiner218 | 2:36cda8980746 | 396 | if(temp&(0x01<<i)) drawPix(blk.height+(i/4), blk.offset+(i%4),1); |
greiner218 | 2:36cda8980746 | 397 | } |
greiner218 | 2:36cda8980746 | 398 | //Draw third face in grid 2 |
greiner218 | 2:36cda8980746 | 399 | temp = (blk.block&FACE2)>>32; |
greiner218 | 2:36cda8980746 | 400 | for (i=0; i<16; i++){ |
greiner218 | 2:36cda8980746 | 401 | if(temp&(0x01<<i)) drawPix(blk.height+(i/4), blk.offset+(i%4),2); |
greiner218 | 2:36cda8980746 | 402 | } |
greiner218 | 2:36cda8980746 | 403 | //Draw fourth face in grid 3 |
greiner218 | 2:36cda8980746 | 404 | temp = (blk.block&FACE3)>>48; |
greiner218 | 2:36cda8980746 | 405 | for (i=0; i<16; i++){ |
greiner218 | 2:36cda8980746 | 406 | if(temp&(0x01<<i)) drawPix(blk.height+(i/4), blk.offset+(i%4),3); |
greiner218 | 2:36cda8980746 | 407 | } |
greiner218 | 2:36cda8980746 | 408 | lcd_mutex.unlock(); |
greiner218 | 2:36cda8980746 | 409 | } |
greiner218 | 2:36cda8980746 | 410 | |
greiner218 | 2:36cda8980746 | 411 | void Board::eraseBlock(Block blk){ |
greiner218 | 2:36cda8980746 | 412 | unsigned long long temp; |
greiner218 | 2:36cda8980746 | 413 | int i = 0; |
greiner218 | 2:36cda8980746 | 414 | lcd_mutex.lock(); |
greiner218 | 2:36cda8980746 | 415 | //Draw front face in grid 0 |
greiner218 | 2:36cda8980746 | 416 | temp = (blk.block&FACE0); |
greiner218 | 2:36cda8980746 | 417 | for (i=0; i<16; i++){ |
greiner218 | 2:36cda8980746 | 418 | if(temp&(0x01<<i)) erasePix(blk.height+(i/4), blk.offset+(i%4),0); |
greiner218 | 2:36cda8980746 | 419 | } |
greiner218 | 2:36cda8980746 | 420 | //Draw second face in grid 1 |
greiner218 | 2:36cda8980746 | 421 | temp = (blk.block&FACE1)>>16; |
greiner218 | 2:36cda8980746 | 422 | for (i=0; i<16; i++){ |
greiner218 | 2:36cda8980746 | 423 | if(temp&(0x01<<i)) erasePix(blk.height+(i/4), blk.offset+(i%4),1); |
greiner218 | 2:36cda8980746 | 424 | } |
greiner218 | 2:36cda8980746 | 425 | //Draw third face in grid 2 |
greiner218 | 2:36cda8980746 | 426 | temp = (blk.block&FACE2)>>32; |
greiner218 | 2:36cda8980746 | 427 | for (i=0; i<16; i++){ |
greiner218 | 2:36cda8980746 | 428 | if(temp&(0x01<<i)) erasePix(blk.height+(i/4), blk.offset+(i%4),2); |
greiner218 | 2:36cda8980746 | 429 | } |
greiner218 | 2:36cda8980746 | 430 | //Draw fourth face in grid 3 |
greiner218 | 2:36cda8980746 | 431 | temp = (blk.block&FACE3)>>48; |
greiner218 | 2:36cda8980746 | 432 | for (i=0; i<16; i++){ |
greiner218 | 2:36cda8980746 | 433 | if(temp&(0x01<<i)) erasePix(blk.height+(i/4), blk.offset+(i%4),3); |
greiner218 | 2:36cda8980746 | 434 | } |
greiner218 | 2:36cda8980746 | 435 | lcd_mutex.unlock(); |
greiner218 | 2:36cda8980746 | 436 | } |
greiner218 | 2:36cda8980746 | 437 | |
greiner218 | 2:36cda8980746 | 438 | void Board::getNewBlock(){ |
greiner218 | 2:36cda8980746 | 439 | activeBlock.block = block_list[rand() % SET_SIZE]; |
greiner218 | 2:36cda8980746 | 440 | activeBlock.offset = DIMX / 2; |
greiner218 | 2:36cda8980746 | 441 | activeBlock.height = DIMZ - 5; |
greiner218 | 2:36cda8980746 | 442 | nextBlock.offset = activeBlock.offset; |
greiner218 | 2:36cda8980746 | 443 | nextBlock.height = activeBlock.height; |
greiner218 | 2:36cda8980746 | 444 | nextBlock.block = activeBlock.block; |
greiner218 | 2:36cda8980746 | 445 | } |
greiner218 | 2:36cda8980746 | 446 | |
greiner218 | 2:36cda8980746 | 447 | unsigned long long shift(unsigned long long value,int offset){ |
greiner218 | 2:36cda8980746 | 448 | unsigned long long rv; |
greiner218 | 2:36cda8980746 | 449 | if (offset > 0) rv = (value<<offset); |
greiner218 | 2:36cda8980746 | 450 | if (offset < 0) rv = (value>>offset); |
greiner218 | 2:36cda8980746 | 451 | if (offset == 0) rv = value; |
greiner218 | 2:36cda8980746 | 452 | return rv; |
greiner218 | 2:36cda8980746 | 453 | } |
greiner218 | 2:36cda8980746 | 454 | |
greiner218 | 2:36cda8980746 | 455 | unsigned long long Board::getFaceLine(int f, int l){ |
greiner218 | 2:36cda8980746 | 456 | unsigned int lower = line[l]&0xFFFFFFFFULL; |
greiner218 | 2:36cda8980746 | 457 | unsigned int upper = (line[l]>>32); |
greiner218 | 2:36cda8980746 | 458 | unsigned long long boardLine = 0; |
greiner218 | 2:36cda8980746 | 459 | switch(f){ |
greiner218 | 2:36cda8980746 | 460 | case 0: |
greiner218 | 2:36cda8980746 | 461 | boardLine = lower&0xFFFF; |
greiner218 | 2:36cda8980746 | 462 | break; |
greiner218 | 2:36cda8980746 | 463 | case 1: |
greiner218 | 2:36cda8980746 | 464 | boardLine = lower>>16; |
greiner218 | 2:36cda8980746 | 465 | break; |
greiner218 | 2:36cda8980746 | 466 | case 2: |
greiner218 | 2:36cda8980746 | 467 | boardLine = upper&0xFFFF; |
greiner218 | 2:36cda8980746 | 468 | break; |
greiner218 | 2:36cda8980746 | 469 | case 3: |
greiner218 | 2:36cda8980746 | 470 | boardLine = upper>>16; |
greiner218 | 2:36cda8980746 | 471 | break; |
greiner218 | 2:36cda8980746 | 472 | default: |
greiner218 | 2:36cda8980746 | 473 | break; |
greiner218 | 2:36cda8980746 | 474 | } |
greiner218 | 2:36cda8980746 | 475 | return boardLine; |
greiner218 | 2:36cda8980746 | 476 | } |
greiner218 | 2:36cda8980746 | 477 | |
greiner218 | 2:36cda8980746 | 478 | void Board::clearLine(int l){ |
greiner218 | 2:36cda8980746 | 479 | //Clears the line indexed by board array |
greiner218 | 2:36cda8980746 | 480 | int i; |
greiner218 | 2:36cda8980746 | 481 | int f; |
greiner218 | 2:36cda8980746 | 482 | for (i=l; i<(DIMZ+3); i++){ |
greiner218 | 2:36cda8980746 | 483 | //Replace the line with the one above it if they are not the same. |
greiner218 | 2:36cda8980746 | 484 | if (line[i] != line[i+1]){ |
greiner218 | 2:36cda8980746 | 485 | line[i] = line[i+1]; |
greiner218 | 2:36cda8980746 | 486 | //Then redraw the current line. |
greiner218 | 2:36cda8980746 | 487 | for (f=0; f<4; f++){ |
greiner218 | 2:36cda8980746 | 488 | redrawBoardLine(i-4, f, getFaceLine(f,i)); |
greiner218 | 2:36cda8980746 | 489 | } |
greiner218 | 2:36cda8980746 | 490 | } |
greiner218 | 2:36cda8980746 | 491 | } |
greiner218 | 2:36cda8980746 | 492 | line[DIMZ+3] = 0xF807F807F807F807ULL; |
greiner218 | 2:36cda8980746 | 493 | for (f=0; f<4; f++){ |
greiner218 | 2:36cda8980746 | 494 | redrawBoardLine(DIMZ-1, f, getFaceLine(f,DIMZ+3)); |
greiner218 | 2:36cda8980746 | 495 | } |
greiner218 | 2:36cda8980746 | 496 | score++; |
greiner218 | 2:36cda8980746 | 497 | drawScore(); |
greiner218 | 2:36cda8980746 | 498 | } |
greiner218 | 2:36cda8980746 | 499 | |
greiner218 | 2:36cda8980746 | 500 | void Board::redrawBoardLine(int l, int f, unsigned long long val){ |
greiner218 | 2:36cda8980746 | 501 | //Redraws the board line using natural index. |
greiner218 | 2:36cda8980746 | 502 | int offset = 0; |
greiner218 | 2:36cda8980746 | 503 | for(offset = 0; offset<DIMX; offset++){ |
greiner218 | 2:36cda8980746 | 504 | //Erase the pixel in the line. |
greiner218 | 2:36cda8980746 | 505 | erasePix(l, offset, f); |
greiner218 | 2:36cda8980746 | 506 | //check if we draw pixel here |
greiner218 | 2:36cda8980746 | 507 | if ( (val&(0x01<<(offset+3))) > 0) drawPix(l,offset,f); |
greiner218 | 2:36cda8980746 | 508 | |
greiner218 | 2:36cda8980746 | 509 | } |
greiner218 | 2:36cda8980746 | 510 | } |
greiner218 | 2:36cda8980746 | 511 | |
greiner218 | 2:36cda8980746 | 512 | void Board::drawScore(){ |
greiner218 | 2:36cda8980746 | 513 | uLCD.locate(6,6); |
greiner218 | 2:36cda8980746 | 514 | uLCD.text_width(1); //4X size text |
greiner218 | 2:36cda8980746 | 515 | uLCD.text_height(1); |
greiner218 | 2:36cda8980746 | 516 | uLCD.background_color(BLUE); |
greiner218 | 2:36cda8980746 | 517 | uLCD.color(BLUE); |
greiner218 | 2:36cda8980746 | 518 | uLCD.textbackground_color(BLACK); |
greiner218 | 2:36cda8980746 | 519 | uLCD.set_font(FONT_7X8); |
greiner218 | 2:36cda8980746 | 520 | uLCD.text_mode(OPAQUE); |
greiner218 | 2:36cda8980746 | 521 | uLCD.printf("Score:"); |
greiner218 | 2:36cda8980746 | 522 | uLCD.locate(6,8); |
greiner218 | 2:36cda8980746 | 523 | uLCD.printf(" %d",score); |
greiner218 | 2:36cda8980746 | 524 | } |
greiner218 | 2:36cda8980746 | 525 | |
greiner218 | 2:36cda8980746 | 526 | void Board::blockFall(){ |
greiner218 | 2:36cda8980746 | 527 | nextBlock.height--; |
greiner218 | 2:36cda8980746 | 528 | int h = nextBlock.height; |
greiner218 | 2:36cda8980746 | 529 | while(check()){ |
greiner218 | 2:36cda8980746 | 530 | h--; |
greiner218 | 2:36cda8980746 | 531 | nextBlock.height--; |
greiner218 | 2:36cda8980746 | 532 | } |
greiner218 | 2:36cda8980746 | 533 | nextBlock.height = h+1; |
greiner218 | 2:36cda8980746 | 534 | } |
greiner218 | 2:36cda8980746 | 535 | |
greiner218 | 2:36cda8980746 | 536 | void Board::checkLose(){ |
greiner218 | 2:36cda8980746 | 537 | int i; |
greiner218 | 2:36cda8980746 | 538 | for (i=DIMLOSE; i<DIMZ; i++){ |
greiner218 | 2:36cda8980746 | 539 | if (line[i+4] != 0xF807F807F807F807ULL)lost=1; |
greiner218 | 2:36cda8980746 | 540 | drawGrid(); |
greiner218 | 2:36cda8980746 | 541 | } |
greiner218 | 2:36cda8980746 | 542 | } |