Stefan Schuermans commited on 2019-07-14 18:59:44
Showing 2 changed files, with 89 additions and 8 deletions.
| ... | ... |
@@ -151,8 +151,8 @@ void Tetris::opConnRecvKey(OpConn *pConn, char key) |
| 151 | 151 |
} |
| 152 | 152 |
|
| 153 | 153 |
/** normal keys for controlling game, |
| 154 |
- deactivated if dropping stone */ |
|
| 155 |
- if (m_dropping) {
|
|
| 154 |
+ deactivated if dropping stone or rows blinking */ |
|
| 155 |
+ if (m_dropping || m_blinking > 0) {
|
|
| 156 | 156 |
return; |
| 157 | 157 |
} |
| 158 | 158 |
|
| ... | ... |
@@ -252,11 +252,17 @@ void Tetris::reinitialize() |
| 252 | 252 |
color2data(m_fileStoneColor, m_stoneColor); |
| 253 | 253 |
// get values |
| 254 | 254 |
valueFromFile(m_fileDelay, c_delayDescr, m_delay); |
| 255 |
+ valueFromFile(m_fileDropDelay, c_dropDelayDescr, m_dropDelay); |
|
| 256 |
+ valueFromFile(m_fileBlinkDelay, c_blinkDelayDescr, m_blinkDelay); |
|
| 255 | 257 |
|
| 256 | 258 |
// initialize field: empty |
| 257 | 259 |
m_field.clear(); |
| 258 | 260 |
m_field.resize(m_height * m_width, -1); |
| 259 | 261 |
|
| 262 |
+ // initialize blinking rows: no row blinking |
|
| 263 |
+ m_rowsBlink.clear(); |
|
| 264 |
+ m_rowsBlink.resize(m_height, false); |
|
| 265 |
+ |
|
| 260 | 266 |
// start with new stone |
| 261 | 267 |
newStone(); |
| 262 | 268 |
|
| ... | ... |
@@ -273,14 +279,16 @@ void Tetris::redraw() |
| 273 | 279 |
// draw background |
| 274 | 280 |
rectFill(0, m_height, 0, m_width, m_backgroundColor); |
| 275 | 281 |
|
| 276 |
- // draw fixed pixels |
|
| 282 |
+ // draw fixed pixels, respect blinking rows |
|
| 277 | 283 |
for (int y = 0, i = 0; y < m_height; ++y) {
|
| 284 |
+ if (! (m_blinking & 1) || ! m_rowsBlink.at(y)) {
|
|
| 278 | 285 |
for (int x = 0; x < m_width; ++x, ++i) {
|
| 279 | 286 |
if (m_field.at(i) >= 0) {
|
| 280 | 287 |
pixel(y, x, m_stoneColor); |
| 281 | 288 |
} |
| 282 | 289 |
} |
| 283 | 290 |
} |
| 291 |
+ } |
|
| 284 | 292 |
|
| 285 | 293 |
// draw current stone |
| 286 | 294 |
drawStone(m_stone, m_rot, m_posY, m_posX); |
| ... | ... |
@@ -292,6 +300,43 @@ void Tetris::redraw() |
| 292 | 300 |
/// process next time step of game |
| 293 | 301 |
void Tetris::timeStep() |
| 294 | 302 |
{
|
| 303 |
+ // blinking of completed rows |
|
| 304 |
+ if (m_blinking > 0) {
|
|
| 305 |
+ |
|
| 306 |
+ // blink rows |
|
| 307 |
+ ++m_blinking; |
|
| 308 |
+ |
|
| 309 |
+ // end of blinking -> remove blinking rows, new stone |
|
| 310 |
+ if (m_blinking >= 8) {
|
|
| 311 |
+ // remove blinking rows |
|
| 312 |
+ for (int b = 0; b < m_height; ++b) {
|
|
| 313 |
+ if (m_rowsBlink.at(b)) {
|
|
| 314 |
+ // move rows 0..b-1 one row down, i.e., to rows 1..b |
|
| 315 |
+ for (int y = b, i = b * m_width + m_width - 1; y > 0; --y) {
|
|
| 316 |
+ for (int x = m_width - 1; x >= 0; --x, --i) {
|
|
| 317 |
+ m_field.at(i) = m_field.at(i - m_width); |
|
| 318 |
+ } |
|
| 319 |
+ } |
|
| 320 |
+ // clear first row |
|
| 321 |
+ for (int x = 0; x < m_width; ++x) {
|
|
| 322 |
+ m_field.at(x) = -1; |
|
| 323 |
+ } |
|
| 324 |
+ // row not blinking any more |
|
| 325 |
+ m_rowsBlink.at(b) = false; |
|
| 326 |
+ } |
|
| 327 |
+ } |
|
| 328 |
+ // blinking done |
|
| 329 |
+ m_blinking = 0; |
|
| 330 |
+ // new stone |
|
| 331 |
+ newStone(); |
|
| 332 |
+ } |
|
| 333 |
+ |
|
| 334 |
+ // redraw image and send frame |
|
| 335 |
+ redraw(); |
|
| 336 |
+ |
|
| 337 |
+ // falling stone |
|
| 338 |
+ } else {
|
|
| 339 |
+ |
|
| 295 | 340 |
// stone can move down by one pixel |
| 296 | 341 |
if (checkStoneFit(m_stone, m_rot, m_posY + 1, m_posX)) {
|
| 297 | 342 |
// move stone down by one pixel |
| ... | ... |
@@ -305,17 +350,50 @@ void Tetris::timeStep() |
| 305 | 350 |
// add stone permanently to field at current position |
| 306 | 351 |
freezeStone(m_stone, m_rot, m_posY, m_posX); |
| 307 | 352 |
drawStone(m_stone, m_rot, m_posY, m_posX); // TODO: frozen color |
| 308 |
- // prepare new stone |
|
| 309 |
- newStone(); |
|
| 353 |
+ // no current stone any more |
|
| 354 |
+ m_stone = -1; |
|
| 355 |
+ // check for completed rows, (afterwards: new stone) |
|
| 356 |
+ checkComplete(); |
|
| 310 | 357 |
} |
| 311 | 358 |
|
| 312 | 359 |
// send updated image buffer as frame |
| 313 | 360 |
sendFrame(); |
| 314 | 361 |
|
| 362 |
+ } // falling stone |
|
| 363 |
+ |
|
| 315 | 364 |
// request next time step |
| 316 | 365 |
planTimeStep(); |
| 317 | 366 |
} |
| 318 | 367 |
|
| 368 |
+/// check for completed rows to disappear (new stone afterwards) |
|
| 369 |
+void Tetris::checkComplete() |
|
| 370 |
+{
|
|
| 371 |
+ // collect y coordinated of completed rows -> m_rowsBlink |
|
| 372 |
+ bool blink = false; |
|
| 373 |
+ for (int y = 0, i = 0; y < m_height; ++y) {
|
|
| 374 |
+ bool complete = true; |
|
| 375 |
+ for (int x = 0; x < m_width; ++x, ++i) {
|
|
| 376 |
+ if (m_field.at(i) < 0) {
|
|
| 377 |
+ complete = false; |
|
| 378 |
+ } |
|
| 379 |
+ } |
|
| 380 |
+ m_rowsBlink.at(y) = complete; |
|
| 381 |
+ if (complete) {
|
|
| 382 |
+ blink = true; |
|
| 383 |
+ } |
|
| 384 |
+ } |
|
| 385 |
+ |
|
| 386 |
+ // no completed rows -> new stone |
|
| 387 |
+ if (! blink) {
|
|
| 388 |
+ newStone(); |
|
| 389 |
+ } |
|
| 390 |
+ |
|
| 391 |
+ // start blinking (start with rows visible, last bit == 0) |
|
| 392 |
+ else {
|
|
| 393 |
+ m_blinking = 2; |
|
| 394 |
+ } |
|
| 395 |
+} |
|
| 396 |
+ |
|
| 319 | 397 |
/// set up a new stone |
| 320 | 398 |
void Tetris::newStone() |
| 321 | 399 |
{
|
| ... | ... |
@@ -121,6 +121,9 @@ protected: |
| 121 | 121 |
/// process next time step of game |
| 122 | 122 |
virtual void timeStep(); |
| 123 | 123 |
|
| 124 |
+ /// check for completed rows to disappear (new stone afterwards) |
|
| 125 |
+ void checkComplete(); |
|
| 126 |
+ |
|
| 124 | 127 |
/// set up a new stone |
| 125 | 128 |
void newStone(); |
| 126 | 129 |
|
| ... | ... |
@@ -181,12 +184,12 @@ protected: |
| 181 | 184 |
int m_posX; ///< x position of current stone |
| 182 | 185 |
int m_posY; ///< y position of current stone |
| 183 | 186 |
bool m_dropping; ///< whether currently dropping a stone |
| 184 |
- int m_blinking; ///< step of blinking: 0 not blinking |
|
| 187 |
+ int m_blinking; ///< step of blinking: 0 not blinking, lsb == 0 -> visible |
|
| 185 | 188 |
|
| 186 | 189 |
/// tetris field (y * m_width + x), -1 for free, >= 0 for pixel from stone |
| 187 | 190 |
std::vector<int> m_field; |
| 188 |
- /// sorted y indices of rows that are currently blinking |
|
| 189 |
- std::vector<int> m_rowsBlink; |
|
| 191 |
+ /// rows that are currently blinking (bool for each row, true when blinking) |
|
| 192 |
+ std::vector<bool> m_rowsBlink; |
|
| 190 | 193 |
}; // class Tetris |
| 191 | 194 |
|
| 192 | 195 |
} // namespace Blinker |
| 193 | 196 |