bd73fc2378f29446e724ee7cc98bf5644cfc300b
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

1) /* Blinker
2)    Copyright 2011-2019 Stefan Schuermans <stefan@blinkenarea.org>
3)    Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
4)    a blinkenarea.org project */
5) 
6) #include <cmath>
7) #include <stdlib.h>
8) #include <string>
9) #include <vector>
10) 
11) #include <BlinkenLib/BlinkenFrame.h>
12) 
13) #include "File.h"
14) #include "Format.h"
15) #include "FormatFile.h"
16) #include "Game.h"
17) #include "Mgrs.h"
18) #include "Module.h"
19) #include "NameFile.h"
20) #include "OpConn.h"
21) #include "OpConnIf.h"
22) #include "OpReqIf.h"
23) #include "OutStreamFile.h"
24) #include "Tetris.h"
25) #include "Time.h"
26) #include "TimeCallee.h"
27) #include "UIntFile.h"
28) 
29) namespace Blinker {
30) 
31) /**
32)  * @brief constructor
33)  * @param[in] name module name
34)  * @param[in] mgrs managers
35)  * @param[in] dirBase base directory
36)  */
37) Tetris::Tetris(const std::string &name, Mgrs &mgrs, const Directory &dirBase):
38)   Game(name, mgrs, dirBase),
39)   m_fileStoneColor(dirBase.getFile("stoneColor")),
40)   m_fileDelay(dirBase.getFile("delay")),
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

41)   m_fileDropDelay(dirBase.getFile("dropDelay")),
Stefan Schuermans tetris: add blink delay

Stefan Schuermans authored 5 years ago

42)   m_fileBlinkDelay(dirBase.getFile("blinkDelay")),
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

43)   m_fileStartSound(dirBase.getFile("startSound")),
44)   m_stoneColor(),
45)   m_delay(c_delayDescr.default_),
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

46)   m_dropDelay(c_dropDelayDescr.default_),
Stefan Schuermans tetris: add blink delay

Stefan Schuermans authored 5 years ago

47)   m_blinkDelay(c_blinkDelayDescr.default_),
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

48)   m_pConn(NULL),
Stefan Schuermans tetris: add blink delay

Stefan Schuermans authored 5 years ago

49)   m_stone(-1), m_rot(-1), m_posX(-1), m_posY(-1),
50)   m_dropping(false), m_blinking(0),
51)   m_field(), m_rowsBlink()
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

52) {
53)   // open operator connection interfaces for player
54)   m_mgrs.m_opMgr.open(m_name, this);
55) }
56) 
57) /// virtual destructor
58) Tetris::~Tetris()
59) {
60)   // close operator connection interface
61)   m_mgrs.m_opMgr.close(m_name);
62) 
63)   // close open operator connection
64)   if (m_pConn) {
65)     m_pConn->close();
66)     m_pConn = NULL;
67)   }
68) }
69) 
70) /// check for update of configuration (derived game), return true on update
71) bool Tetris::updateConfigGame()
72) {
73)   bool ret = false;
74) 
75)   // color file was modified -> convert color, return true for update
76)   // cfg value file was updated -> read new cfg value, return true for update
Stefan Schuermans tetris: always check all co...

Stefan Schuermans authored 5 years ago

77)   if (colorUpdate(m_fileStoneColor, m_stoneColor)) {
78)     ret = true;
79)   }
80)   if (valueUpdate(m_fileDelay, c_delayDescr, m_delay)) {
81)     ret = true;
82)   }
83)   if (valueUpdate(m_fileDropDelay, c_dropDelayDescr, m_dropDelay)) {
84)     ret = true;
85)   }
86)   if (valueUpdate(m_fileBlinkDelay, c_blinkDelayDescr, m_blinkDelay)) {
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

87)     ret = true;
88)   }
89) 
90)   // sound name file was modified -> re-read sound name, no other update needed
91)   soundUpdate(m_fileStartSound);
92) 
93)   return ret;
94) }
95) 
96) /**
97)  * @brief check if accepting new operator connection is possible
98)  * @param[in] name operator interface name
99)  * @return if accepting new connection is possible
100)  */
101) bool Tetris::acceptNewOpConn(const std::string &name)
102) {
103)   (void)name;
104) 
105)   // accept player if no one there yet
106)   return ! m_pConn;
107) }
108) 
109) /**
110)  * @brief new operator connection
111)  * @param[in] name operator interface name
112)  * @param[in] pConn operator connection object
113)  *
114)  * The new connection may not yet be used for sending inside this callback.
115)  */
116) void Tetris::newOpConn(const std::string &name, OpConn *pConn)
117) {
118)   (void)name;
119) 
120)   // player arrives and starts game
121)   if (! m_pConn) {
122)     m_pConn = pConn;
123)     requestOpConnSound(m_pConn, m_fileStartSound);
124)     activate();
125)   }
126)   // close imcoming connection as soon as possible, nothing else happens
127)   else {
128)     requestOpConnClose(pConn);
129)     return;
130)   }
131) }
132) 
133) /**
134)  * @brief key command received on operator connection
135)  * @param[in] pConn operator connection object
136)  * @param[in] key key that was pressed
137)  */
138) void Tetris::opConnRecvKey(OpConn *pConn, char key)
139) {
140)   // hash -> hang up
141)   if (key == '#') {
142)     opConnClose(pConn);
143)     pConn->close();
144)     return;
145)   }
146) 
147)   // star -> inform player about game
148)   if (key == '*') {
149)     playOpConnSound(pConn, m_fileStartSound);
150)     return;
151)   }
152) 
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

153)   /** normal keys for controlling game,
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

154)       deactivated if dropping stone or rows blinking */
155)   if (m_dropping || m_blinking > 0) {
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

156)     return;
157)   }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

158) 
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

159)   // move left
160)   if (key == '4') {
161)     if (checkStoneFit(m_stone, m_rot, m_posY, m_posX - 1)) {
162)       wipeStone(m_stone, m_rot, m_posY, m_posX);
163)       m_posX -= 1;
164)       drawStone(m_stone, m_rot, m_posY, m_posX); // TODO: active color
Stefan Schuermans tetris: output frame on sto...

Stefan Schuermans authored 5 years ago

165)       sendFrame();
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

166)     }
167)     return;
168)   }
169) 
170)   // move right
171)   if (key == '6') {
172)     if (checkStoneFit(m_stone, m_rot, m_posY, m_posX + 1)) {
173)       wipeStone(m_stone, m_rot, m_posY, m_posX);
174)       m_posX += 1;
175)       drawStone(m_stone, m_rot, m_posY, m_posX); // TODO: active color
Stefan Schuermans tetris: output frame on sto...

Stefan Schuermans authored 5 years ago

176)       sendFrame();
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

177)     }
178)     return;
179)   }
180) 
181)   // rotate left
182)   if (key == '1') {
183)     int new_rot = m_rot - 1;
184)     if (new_rot < 0) {
185)       new_rot = c_rotCnt - 1;
186)     }
187)     if (checkStoneFit(m_stone, new_rot, m_posY, m_posX)) {
188)       wipeStone(m_stone, m_rot, m_posY, m_posX);
189)       m_rot = new_rot;
190)       drawStone(m_stone, m_rot, m_posY, m_posX); // TODO: active color
Stefan Schuermans tetris: output frame on sto...

Stefan Schuermans authored 5 years ago

191)       sendFrame();
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

192)     }
193)     return;
194)   }
195) 
196)   // rotate right
197)   if (key == '2' || key == '3') {
198)     int new_rot = m_rot + 1;
199)     if (new_rot >= c_rotCnt) {
200)       new_rot = 0;
201)     }
202)     if (checkStoneFit(m_stone, new_rot, m_posY, m_posX)) {
203)       wipeStone(m_stone, m_rot, m_posY, m_posX);
204)       m_rot = new_rot;
205)       drawStone(m_stone, m_rot, m_posY, m_posX); // TODO: active color
Stefan Schuermans tetris: output frame on sto...

Stefan Schuermans authored 5 years ago

206)       sendFrame();
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

207)     }
208)     return;
209)   }
210) 
211)   // drop stone
212)   if (key == '8') {
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

213)     m_dropping = true;
214)     planTimeStep(); // stone falls fater now -> update time callback
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

215)     return;
216)   }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

217) }
218) 
219) /**
220)  * @brief play command received on operator connection
221)  * @param[in] pConn operator connection object
222)  * @param[in] sound name of sound to play
223)  */
224) void Tetris::opConnRecvPlay(OpConn *pConn, const std::string &sound)
225) {
226)   (void)pConn;
227)   (void)sound;
228) }
229) 
230) /**
231)  * @brief operator connection is closed
232)  * @param[in] pConn operator connection object
233)  *
234)  * The connection may not be used for sending any more in this callback.
235)  */
236) void Tetris::opConnClose(OpConn *pConn)
237) {
238)   // remove coperator connection from requests (if it was in)
239)   forgetOpConn(pConn);
240) 
241)   // player leaves -> deactivate game
242)   if (pConn == m_pConn) {
243)     m_pConn = NULL;
244)     deactivate();
245)   }
246) }
247) 
248) /// re-initialize game (e.g. due to config change)
249) void Tetris::reinitialize()
250) {
251)   // convert colors
252)   color2data(m_fileStoneColor, m_stoneColor);
253)   // get values
254)   valueFromFile(m_fileDelay, c_delayDescr, m_delay);
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

255)   valueFromFile(m_fileDropDelay, c_dropDelayDescr, m_dropDelay);
256)   valueFromFile(m_fileBlinkDelay, c_blinkDelayDescr, m_blinkDelay);
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

257) 
258)   // initialize field: empty
259)   m_field.clear();
260)   m_field.resize(m_height * m_width, -1);
261) 
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

262)   // initialize blinking rows: no row blinking
263)   m_rowsBlink.clear();
264)   m_rowsBlink.resize(m_height, false);
265) 
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

266)   // start with new stone
267)   newStone();
268) 
269)   // redraw image and send frame
270)   redraw();
271) 
272)   // request first time step if needed
273)   planTimeStep();
274) }
275) 
276) /// redraw current game image, expected to call sendFrame() at end
277) void Tetris::redraw()
278) {
279)   // draw background
280)   rectFill(0, m_height, 0, m_width, m_backgroundColor);
281) 
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

282)   // draw fixed pixels, respect blinking rows
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

283)   for (int y = 0, i = 0; y < m_height; ++y) {
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

284)     if (! (m_blinking & 1) || ! m_rowsBlink.at(y)) {
285)       for (int x = 0; x < m_width; ++x, ++i) {
286)         if (m_field.at(i) >= 0) {
287)           pixel(y, x, m_stoneColor);
288)         }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

289)       }
290)     }
291)   }
292) 
293)   // draw current stone
294)   drawStone(m_stone, m_rot, m_posY, m_posX);
295) 
296)   // send updated image buffer as frame
297)   sendFrame();
298) }
299) 
300) /// process next time step of game
301) void Tetris::timeStep()
302) {
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

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)     }
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

333) 
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

334)     // redraw image and send frame
335)     redraw();
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

336) 
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

337)   // falling stone
338)   } else {
339) 
340)     // stone can move down by one pixel
341)     if (checkStoneFit(m_stone, m_rot, m_posY + 1, m_posX)) {
342)       // move stone down by one pixel
343)       wipeStone(m_stone, m_rot, m_posY, m_posX);
344)       m_posY += 1;
345)       drawStone(m_stone, m_rot, m_posY, m_posX); // TODO: active color
346)     }
347) 
348)     // stone cannot move down by one pixel
349)     else {
350)       // add stone permanently to field at current position
351)       freezeStone(m_stone, m_rot, m_posY, m_posX);
352)       drawStone(m_stone, m_rot, m_posY, m_posX); // TODO: frozen color
353)       // no current stone any more
354)       m_stone = -1;
355)       // check for completed rows, (afterwards: new stone)
356)       checkComplete();
357)     }
358) 
359)     // send updated image buffer as frame
360)     sendFrame();
361) 
362)   } // falling stone
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

363) 
364)   // request next time step
365)   planTimeStep();
366) }
367) 
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

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) 
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

397) /// set up a new stone
398) void Tetris::newStone()
399) {
400)   // random stone, random rotation
401)   m_stone = rand() % c_stoneCnt;
402)   m_rot = rand() % c_rotCnt;
403) 
404)   // postion: two pixels above top middle
405)   m_posX = (m_width - 1) / 2;
406)   m_posY = -2;
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

407) 
408)   // stone is not being dropped yet
409)   m_dropping = false;
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

410) }
411) 
412) /// set time for next time step of game - or unset if not needed
413) void Tetris::planTimeStep()
414) {
415)   // no time call needed if not active
416)   if (! isActive()) {
417)     unsetTimeStep();
418)     return;
419)   }
420) 
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

421)   // compute interval based on game state
Stefan Schuermans tetris: add blink delay

Stefan Schuermans authored 5 years ago

422)   int interval_ms = m_delay;
423)   if (m_dropping) {
424)     interval_ms = m_dropDelay;
425)   } else if (m_blinking > 0) {
426)     interval_ms = m_blinkDelay;
427)   }
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

428)   float interval = 1e-3f * interval_ms;
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

429) 
430)   // request next time call
431)   Time stepTime;
432)   stepTime.fromFloatSec(interval);
433)   setTimeStep(Time::now() + stepTime);
434) }
435) 
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

436) /// get rotatation of stone from stone/rotation index (or NULL in invalid)
437) Tetris::RotStone const * Tetris::getRotStone(int stone, int rot)
438) {
439)   if (! checkLimitInt(stone, 0, c_stoneCnt -1) ||
440)       ! checkLimitInt(rot, 0, c_rotCnt - 1)) {
441)     return NULL; // invalid stone or rotation
442)   }
443)   return &c_stones[stone].rot[rot];
444) }
445) 
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

446) /// check if stone fits at position
447) bool Tetris::checkStoneFit(int stone, int rot, int y, int x) const
448) {
449)   // get rotation of stone
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

450)   RotStone const *rotStone = getRotStone(stone, rot);
451)   if (! rotStone) {
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

452)     return false; // invalid stone or rotation -> does not fit
453)   }
454) 
455)   // check pixels
456)   for (int p = 0; p < c_pixelCnt; ++p) {
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

457)     int py = y + rotStone->pixels[p].y;
458)     int px = x + rotStone->pixels[p].x;
459)     if (py > m_height - 1 || ! checkLimitInt(px, 0, m_width - 1)) {
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

460)       return false; // outside field (except at top) -> does not fit
461)     }
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

462)     if (py >= 0) { // do not check above top
463)       int pi = py * m_width + px;
464)       if (m_field.at(pi) >= 0) {
465)         return false; // occupixed pixel -> does not fit
466)       }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

467)     }
468)   }
469) 
470)   // all checks passed -> stone fits
471)   return true;
472) }
473) 
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

474) /// freeze stone to field at position
475) void Tetris::freezeStone(int stone, int rot, int y, int x)
476) {
477)   // get rotation of stone
478)   RotStone const *rotStone = getRotStone(stone, rot);
479)   if (! rotStone) {
480)     return; // invalid stone or rotation -> nothing to do
481)   }
482) 
483)   // add pixels to field
484)   for (int p = 0; p < c_pixelCnt; ++p) {
485)     int py = y + rotStone->pixels[p].y;
486)     int px = x + rotStone->pixels[p].x;
487)     if (checkLimitInt(py, 0, m_height - 1) &&
488)         checkLimitInt(px, 0, m_width - 1)) {
489)       int pi = py * m_width + px;
490)       m_field.at(pi) = stone; // mark pixel in field with stone index
491)     }
492)   }
493) }
494) 
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

495) /// draw a stone to image buffer
496) void Tetris::drawStone(int stone, int rot, int y, int x)
497) {
498)   colorStone(stone, rot, y, x, m_stoneColor);
499) }
500) 
501) /// wipe a stone from image buffer (i.e. replace it with background color)
502) void Tetris::wipeStone(int stone, int rot, int y, int x)
503) {
504)   colorStone(stone, rot, y, x, m_backgroundColor);
505) }
506) 
507) /// set shape of stone to color in image buffer
508) void Tetris::colorStone(int stone, int rot, int y, int x,
509)                         ColorData const &color)
510) {
511)   // get rotation of stone
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

512)   RotStone const *rotStone = getRotStone(stone, rot);
513)   if (! rotStone) {
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

514)     return; // invalid stone or rotation -> nothing to do
515)   }
516) 
517)   // color pixels
518)   for (int p = 0; p < c_pixelCnt; ++p) {
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

519)     pixel(y + rotStone->pixels[p].y, x + rotStone->pixels[p].x, color);
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

520)   }
521) }
522) 
523) /// stone data
524) Tetris::Stone const Tetris::c_stones[7] = {
525)   // the I
526)   { {
527)       { { { -2,  0 }, { -1,  0 }, {  0,  0 }, {  1,  0 } } },
528)       { { {  0, -2 }, {  0, -1 }, {  0,  0 }, {  0,  1 } } },
529)       { { { -2,  0 }, { -1,  0 }, {  0,  0 }, {  1,  0 } } },
530)       { { {  0, -2 }, {  0, -1 }, {  0,  0 }, {  0,  1 } } },
531)   } },
532)   // the L
533)   { {
534)       { { {  1, -1 }, { -1,  0 }, {  0,  0 }, {  1,  0 } } },
535)       { { {  0, -1 }, {  0,  0 }, {  0,  1 }, {  1,  1 } } },
536)       { { { -1,  0 }, {  0,  0 }, {  1,  0 }, { -1,  1 } } },
537)       { { { -1, -1 }, {  0, -1 }, {  0,  0 }, {  0,  1 } } },
538)   } },
539)   // the J
540)   { {
541)       { { { -1, -1 }, { -1,  0 }, {  0,  0 }, {  1,  0 } } },
542)       { { {  0, -1 }, {  1, -1 }, {  0,  0 }, {  0,  1 } } },
543)       { { { -1,  0 }, {  0,  0 }, {  1,  0 }, {  1,  1 } } },
544)       { { {  0, -1 }, {  0,  0 }, { -1,  1 }, {  0,  1 } } },
545)   } },
546)   // the T
547)   { {
548)       { { {  0, -1 }, { -1,  0 }, {  0,  0 }, {  1,  0 } } },
549)       { { {  0, -1 }, {  0,  0 }, {  1,  0 }, {  0,  1 } } },
550)       { { { -1,  0 }, {  0,  0 }, {  1,  0 }, {  0,  1 } } },
551)       { { {  0, -1 }, { -1,  0 }, {  0,  0 }, {  0,  1 } } },
552)   } },
553)   // the O
554)   { {
555)       { { {  0, -1 }, {  1, -1 }, {  0,  0 }, {  1,  0 } } },
556)       { { {  0, -1 }, {  1, -1 }, {  0,  0 }, {  1,  0 } } },
557)       { { {  0, -1 }, {  1, -1 }, {  0,  0 }, {  1,  0 } } },
558)       { { {  0, -1 }, {  1, -1 }, {  0,  0 }, {  1,  0 } } },
559)   } },
560)   // the Z
561)   { {
562)       { { { -1, -1 }, {  0, -1 }, {  0,  0 }, {  1,  0 } } },
563)       { { {  0, -1 }, { -1,  0 }, {  0,  0 }, { -1,  1 } } },
564)       { { { -1, -1 }, {  0, -1 }, {  0,  0 }, {  1,  0 } } },
565)       { { {  0, -1 }, { -1,  0 }, {  0,  0 }, { -1,  1 } } },
566)   } },
567)   // the S
568)   { {
569)       { { {  0, -1 }, {  1, -1 }, { -1,  0 }, {  0,  0 } } },
570)       { { { -1, -1 }, { -1,  0 }, {  0,  0 }, {  0,  1 } } },
571)       { { {  0, -1 }, {  1, -1 }, { -1,  0 }, {  0,  0 } } },
572)       { { { -1, -1 }, { -1,  0 }, {  0,  0 }, {  0,  1 } } },
573)   } },
574) };
575) 
576) /// number of stones
577) int const Tetris::c_stoneCnt = sizeof(Tetris::c_stones) /
578)                                sizeof(Tetris::c_stones[0]);
579) /// number of rotations per stone
580) int const Tetris::c_rotCnt = sizeof(Tetris::Stone::rot) /
581)                              sizeof(Tetris::Stone::rot[0]);
582) /// number of pixels per stone
583) int const Tetris::c_pixelCnt = sizeof(Tetris::RotStone::pixels) /
584)                                sizeof(Tetris::RotStone::pixels[0]);
585) 
586) /// descriptor for delay value
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

587) Tetris::ValueDescr const Tetris::c_delayDescr = { 400, 200, 1000 };
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

588) 
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

589) /// descriptor for delay value during dropping a stone
590) Tetris::ValueDescr const Tetris::c_dropDelayDescr = { 100, 50, 250 };
591) 
Stefan Schuermans tetris: add blink delay

Stefan Schuermans authored 5 years ago

592) /// descriptor for delay value during blinking of disappearing rows
593) Tetris::ValueDescr const Tetris::c_blinkDelayDescr = { 50, 50, 250 };
594)