323d46e40d330a95c176798208854845e0f2759e
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: complete game logic

Stefan Schuermans authored 5 years ago

43)   m_fileGameOverDelay(dirBase.getFile("gameOverDelay")),
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

44)   m_fileStartSound(dirBase.getFile("startSound")),
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

45)   m_fileRowCompleteSound(dirBase.getFile("rowCompleteSound")),
46)   m_fileGameOverSound(dirBase.getFile("gameOverSound")),
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

47)   m_stoneColor(),
48)   m_delay(c_delayDescr.default_),
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

50)   m_blinkDelay(c_blinkDelayDescr.default_),
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

51)   m_gameOverDelay(c_gameOverDelayDescr.default_),
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

53)   m_stone(-1), m_rot(-1), m_posX(-1), m_posY(-1),
Stefan Schuermans tetris: one time step at ga...

Stefan Schuermans authored 5 years ago

54)   m_dropping(false), m_blinking(0), m_completed(0), m_gameOver(false),
Stefan Schuermans tetris: add blink delay

Stefan Schuermans authored 5 years ago

55)   m_field(), m_rowsBlink()
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

56) {
57)   // open operator connection interfaces for player
58)   m_mgrs.m_opMgr.open(m_name, this);
59) }
60) 
61) /// virtual destructor
62) Tetris::~Tetris()
63) {
64)   // close operator connection interface
65)   m_mgrs.m_opMgr.close(m_name);
66) 
67)   // close open operator connection
68)   if (m_pConn) {
69)     m_pConn->close();
70)     m_pConn = NULL;
71)   }
72) }
73) 
Stefan Schuermans change of some game params...

Stefan Schuermans authored 5 years ago

74) /**
75)  * @brief check for update of configuration (derived game)
76)  * @param[in,out] doReinit set to true to ask for reinitialization
77)  * @param[in,out] doRedraw set to true to ask for redrawing
78)  */
79) void Tetris::updateConfigGame(bool &doReinit, bool &doRedraw)
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

80) {
Stefan Schuermans change of some game params...

Stefan Schuermans authored 5 years ago

81)   (void)doReinit;
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

82) 
Stefan Schuermans change of some game params...

Stefan Schuermans authored 5 years ago

83)   // color file was modified -> convert color, ask for redraw
84)   if (colorUpdate(m_fileStoneColor, m_stoneColor)) { doRedraw = true; }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

85) 
Stefan Schuermans change of some game params...

Stefan Schuermans authored 5 years ago

86)   // delay cfg value file was updated -> read new delay cfg value, no re-*
87)   valueUpdate(m_fileDelay, c_delayDescr, m_delay);
88)   valueUpdate(m_fileDropDelay, c_dropDelayDescr, m_dropDelay);
89)   valueUpdate(m_fileBlinkDelay, c_blinkDelayDescr, m_blinkDelay);
90)   valueUpdate(m_fileGameOverDelay, c_gameOverDelayDescr, m_gameOverDelay);
91) 
92)   // sound name file was modified -> re-read sound name, no reinit/draw needed
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

93)   soundUpdate(m_fileStartSound);
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

94)   soundUpdate(m_fileRowCompleteSound);
95)   soundUpdate(m_fileGameOverSound);
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

96) }
97) 
98) /**
99)  * @brief check if accepting new operator connection is possible
100)  * @param[in] name operator interface name
101)  * @return if accepting new connection is possible
102)  */
103) bool Tetris::acceptNewOpConn(const std::string &name)
104) {
105)   (void)name;
106) 
Stefan Schuermans add game interlock

Stefan Schuermans authored 5 years ago

107)   // accept player if no one there yet and game can be activated
108)   return ! m_pConn && canActivate();
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

109) }
110) 
111) /**
112)  * @brief new operator connection
113)  * @param[in] name operator interface name
114)  * @param[in] pConn operator connection object
115)  *
116)  * The new connection may not yet be used for sending inside this callback.
117)  */
118) void Tetris::newOpConn(const std::string &name, OpConn *pConn)
119) {
120)   (void)name;
121) 
122)   // player arrives and starts game
123)   if (! m_pConn) {
Stefan Schuermans add game interlock

Stefan Schuermans authored 5 years ago

124)     if (activate()) {
125)       m_pConn = pConn;
126)       requestOpConnSound(m_pConn, m_fileStartSound);
127)     } else {
128)       // activation failed (interlock), close connection as soon as possible
129)       requestOpConnClose(pConn);
130)     }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

131)   }
Stefan Schuermans add game interlock

Stefan Schuermans authored 5 years ago

132)   // close imcoming connection as soon as possible
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

133)   else {
134)     requestOpConnClose(pConn);
135)   }
136) }
137) 
138) /**
139)  * @brief key command received on operator connection
140)  * @param[in] pConn operator connection object
141)  * @param[in] key key that was pressed
142)  */
143) void Tetris::opConnRecvKey(OpConn *pConn, char key)
144) {
145)   // hash -> hang up
146)   if (key == '#') {
147)     opConnClose(pConn);
148)     pConn->close();
149)     return;
150)   }
151) 
152)   // star -> inform player about game
153)   if (key == '*') {
154)     playOpConnSound(pConn, m_fileStartSound);
155)     return;
156)   }
157) 
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

158)   /** normal keys for controlling game,
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

159)       deactivated if dropping stone, rows blinking or end of game */
Stefan Schuermans tetris: one time step at ga...

Stefan Schuermans authored 5 years ago

160)   if (m_dropping || m_blinking > 0 || m_gameOver) {
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

161)     return;
162)   }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

163) 
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

164)   // move left
165)   if (key == '4') {
166)     if (checkStoneFit(m_stone, m_rot, m_posY, m_posX - 1)) {
167)       wipeStone(m_stone, m_rot, m_posY, m_posX);
168)       m_posX -= 1;
169)       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

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

Stefan Schuermans authored 5 years ago

171)     }
172)     return;
173)   }
174) 
175)   // move right
176)   if (key == '6') {
177)     if (checkStoneFit(m_stone, m_rot, m_posY, m_posX + 1)) {
178)       wipeStone(m_stone, m_rot, m_posY, m_posX);
179)       m_posX += 1;
180)       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

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

Stefan Schuermans authored 5 years ago

182)     }
183)     return;
184)   }
185) 
186)   // rotate left
187)   if (key == '1') {
188)     int new_rot = m_rot - 1;
189)     if (new_rot < 0) {
190)       new_rot = c_rotCnt - 1;
191)     }
192)     if (checkStoneFit(m_stone, new_rot, m_posY, m_posX)) {
193)       wipeStone(m_stone, m_rot, m_posY, m_posX);
194)       m_rot = new_rot;
195)       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

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

Stefan Schuermans authored 5 years ago

197)     }
198)     return;
199)   }
200) 
201)   // rotate right
202)   if (key == '2' || key == '3') {
203)     int new_rot = m_rot + 1;
204)     if (new_rot >= c_rotCnt) {
205)       new_rot = 0;
206)     }
207)     if (checkStoneFit(m_stone, new_rot, m_posY, m_posX)) {
208)       wipeStone(m_stone, m_rot, m_posY, m_posX);
209)       m_rot = new_rot;
210)       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

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

Stefan Schuermans authored 5 years ago

212)     }
213)     return;
214)   }
215) 
216)   // drop stone
217)   if (key == '8') {
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

218)     m_dropping = true;
Stefan Schuermans fix comment typo

Stefan Schuermans authored 5 years ago

219)     planTimeStep(); // stone falls faster now -> update time callback
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

220)     return;
221)   }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

260)   valueFromFile(m_fileDropDelay, c_dropDelayDescr, m_dropDelay);
261)   valueFromFile(m_fileBlinkDelay, c_blinkDelayDescr, m_blinkDelay);
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

262)   valueFromFile(m_fileGameOverDelay, c_gameOverDelayDescr, m_gameOverDelay);
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

263) 
264)   // initialize field: empty
265)   m_field.clear();
266)   m_field.resize(m_height * m_width, -1);
267) 
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

268)   // initialize blinking rows: no row blinking
269)   m_rowsBlink.clear();
270)   m_rowsBlink.resize(m_height, false);
271) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

272)   // no rows blinking or completed, game not over yet
273)   m_blinking = 0;
274)   m_completed = 0;
Stefan Schuermans tetris: one time step at ga...

Stefan Schuermans authored 5 years ago

275)   m_gameOver = false;
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

276) 
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

277)   // start with new stone
278)   newStone();
279) 
280)   // redraw image and send frame
281)   redraw();
282) 
283)   // request first time step if needed
284)   planTimeStep();
285) }
286) 
287) /// redraw current game image, expected to call sendFrame() at end
288) void Tetris::redraw()
289) {
290)   // draw background
291)   rectFill(0, m_height, 0, m_width, m_backgroundColor);
292) 
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

295)     if (! (m_blinking & 1) || ! m_rowsBlink.at(y)) {
296)       for (int x = 0; x < m_width; ++x, ++i) {
297)         if (m_field.at(i) >= 0) {
298)           pixel(y, x, m_stoneColor);
299)         }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

300)       }
301)     }
302)   }
303) 
304)   // draw current stone
305)   drawStone(m_stone, m_rot, m_posY, m_posX);
306) 
307)   // send updated image buffer as frame
308)   sendFrame();
309) }
310) 
311) /// process next time step of game
312) void Tetris::timeStep()
313) {
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

314)   // count time at end of game
Stefan Schuermans tetris: one time step at ga...

Stefan Schuermans authored 5 years ago

315)   if (m_gameOver) {
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

316)     timeGameOver();
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

317)   // blinking of completed rows
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

318)   } else if (m_blinking > 0) {
319)     timeBlinkRows();
320)   // falling stone
321)   } else {
322)     timeStone();
323)   }
324) 
325)   // request next time step
326)   planTimeStep();
327) }
328) 
329) /// count time at end of game
330) void Tetris::timeGameOver()
331) {
Stefan Schuermans tetris: one time step at ga...

Stefan Schuermans authored 5 years ago

332)   // close operator connection
333)   if (m_pConn) {
334)     forgetOpConn(m_pConn); // remove from requests (if it was in)
335)     m_pConn->close();
336)     m_pConn = NULL;
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

337)   }
Stefan Schuermans tetris: one time step at ga...

Stefan Schuermans authored 5 years ago

338) 
339)   // deactivate game
340)   deactivate();
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

341) }
342) 
343) /// blink completed rows
344) void Tetris::timeBlinkRows()
345) {
346)   // blink rows
347)   ++m_blinking;
348) 
349)   // end of blinking -> remove blinking rows, new stone
350)   if (m_blinking >= 8) {
351)     // remove blinking rows
352)     for (int b = 0; b < m_height; ++b) {
353)       if (m_rowsBlink.at(b)) {
354)         // move rows 0..b-1 one row down, i.e., to rows 1..b
355)         for (int y = b, i = b * m_width + m_width - 1; y > 0; --y) {
356)           for (int x = m_width - 1; x >= 0; --x, --i) {
357)             m_field.at(i) = m_field.at(i - m_width);
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

358)           }
359)         }
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

360)         // clear first row
361)         for (int x = 0; x < m_width; ++x) {
362)           m_field.at(x) = -1;
363)         }
364)         // row not blinking any more
365)         m_rowsBlink.at(b) = false;
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

366)       }
367)     }
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

368)     // blinking done
369)     m_blinking = 0;
370)     // new stone
371)     newStone();
372)   }
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

373) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

374)   // redraw image and send frame
375)   redraw();
376) }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

377) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

378) /// falling stone
379) void Tetris::timeStone()
380) {
381)   // stone can move down by one pixel
382)   if (checkStoneFit(m_stone, m_rot, m_posY + 1, m_posX)) {
383)     // move stone down by one pixel
384)     wipeStone(m_stone, m_rot, m_posY, m_posX);
385)     m_posY += 1;
386)     drawStone(m_stone, m_rot, m_posY, m_posX); // TODO: active color
387)   }
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

388) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

389)   // stone cannot move down by one pixel
390)   else {
391)     // add stone permanently to field at current position
392)     freezeStone(m_stone, m_rot, m_posY, m_posX);
393)     drawStone(m_stone, m_rot, m_posY, m_posX); // TODO: frozen color
394) 
395)     // overflow of game field -> game over
396)     if (checkStoneOverflow(m_stone, m_rot, m_posY, m_posX)) {
397)       // unset stone
398)       m_stone = -1;
399)       // game over
Stefan Schuermans tetris: one time step at ga...

Stefan Schuermans authored 5 years ago

400)       m_gameOver = true;
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

401)       playOpConnSound(m_pConn, m_fileGameOverSound);
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

402)     }
403) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

404)     // no overflow
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

405)     else {
406)       // no current stone any more
407)       m_stone = -1;
408)       // check for completed rows, (afterwards: new stone)
409)       checkComplete();
410)     }
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

411)   }
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

412) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

413)   // send updated image buffer as frame
414)   sendFrame();
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

415) }
416) 
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

417) /// check for completed rows to disappear (new stone afterwards)
418) void Tetris::checkComplete()
419) {
420)   // collect y coordinated of completed rows -> m_rowsBlink
421)   bool blink = false;
422)   for (int y = 0, i = 0; y < m_height; ++y) {
423)     bool complete = true;
424)     for (int x = 0; x < m_width; ++x, ++i) {
425)       if (m_field.at(i) < 0) {
426)         complete = false;
427)       }
428)     }
429)     m_rowsBlink.at(y) = complete;
430)     if (complete) {
431)       blink = true;
432)     }
433)   }
434) 
435)   // no completed rows -> new stone
436)   if (! blink) {
437)     newStone();
438)   }
439) 
440)   // start blinking (start with rows visible, last bit == 0)
441)   else {
442)     m_blinking = 2;
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

443)     playOpConnSound(m_pConn, m_fileRowCompleteSound);
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

444)   }
445) }
446) 
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

447) /// set up a new stone
448) void Tetris::newStone()
449) {
450)   // random stone, random rotation
451)   m_stone = rand() % c_stoneCnt;
452)   m_rot = rand() % c_rotCnt;
453) 
454)   // postion: two pixels above top middle
455)   m_posX = (m_width - 1) / 2;
456)   m_posY = -2;
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

457) 
458)   // stone is not being dropped yet
459)   m_dropping = false;
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

460) }
461) 
462) /// set time for next time step of game - or unset if not needed
463) void Tetris::planTimeStep()
464) {
465)   // no time call needed if not active
466)   if (! isActive()) {
467)     unsetTimeStep();
468)     return;
469)   }
470) 
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

472)   int interval_ms = m_delay;
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

473)   int speedup = m_completed;
Stefan Schuermans tetris: one time step at ga...

Stefan Schuermans authored 5 years ago

474)   if (m_gameOver) {
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

475)     interval_ms = m_gameOverDelay;
476)     speedup = 0;
Stefan Schuermans tetris: add blink delay

Stefan Schuermans authored 5 years ago

477)   } else if (m_blinking > 0) {
478)     interval_ms = m_blinkDelay;
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

479)   } else if (m_dropping) {
480)     interval_ms = m_dropDelay;
Stefan Schuermans tetris: add blink delay

Stefan Schuermans authored 5 years ago

481)   }
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

482)   float scale = 0.3f + 0.7f * expf(-0.3f * speedup);
483)   float interval = 1e-3f * interval_ms * scale;
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

484) 
485)   // request next time call
486)   Time stepTime;
487)   stepTime.fromFloatSec(interval);
488)   setTimeStep(Time::now() + stepTime);
489) }
490) 
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

491) /// get rotatation of stone from stone/rotation index (or NULL in invalid)
492) Tetris::RotStone const * Tetris::getRotStone(int stone, int rot)
493) {
494)   if (! checkLimitInt(stone, 0, c_stoneCnt -1) ||
495)       ! checkLimitInt(rot, 0, c_rotCnt - 1)) {
496)     return NULL; // invalid stone or rotation
497)   }
498)   return &c_stones[stone].rot[rot];
499) }
500) 
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

501) /// check if stone fits at position
502) bool Tetris::checkStoneFit(int stone, int rot, int y, int x) const
503) {
504)   // get rotation of stone
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

507)     return false; // invalid stone or rotation -> does not fit
508)   }
509) 
510)   // check pixels
511)   for (int p = 0; p < c_pixelCnt; ++p) {
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

517)     if (py >= 0) { // do not check above top
518)       int pi = py * m_width + px;
519)       if (m_field.at(pi) >= 0) {
520)         return false; // occupixed pixel -> does not fit
521)       }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

522)     }
523)   }
524) 
525)   // all checks passed -> stone fits
526)   return true;
527) }
528) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

529) /// check if stone overflow game field
530) bool Tetris::checkStoneOverflow(int stone, int rot, int y, int x) const
531) {
532)   // get rotation of stone
533)   RotStone const *rotStone = getRotStone(stone, rot);
534)   if (! rotStone) {
535)     return true; // invalid stone or rotation -> overflow
536)   }
537) 
538)   // check pixels for overflow
539)   for (int p = 0; p < c_pixelCnt; ++p) {
540)     int py = y + rotStone->pixels[p].y;
541)     int px = x + rotStone->pixels[p].x;
542)     if (! checkLimitInt(py, 0, m_height -1) ||
543)         ! checkLimitInt(px, 0, m_width - 1)) {
544)       return true; // outside field (including top) -> overflow
545)     }
546)   }
547) 
548)   // all checks passed -> no overflow
549)   return false;
550) }
551) 
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

552) /// freeze stone to field at position
553) void Tetris::freezeStone(int stone, int rot, int y, int x)
554) {
555)   // get rotation of stone
556)   RotStone const *rotStone = getRotStone(stone, rot);
557)   if (! rotStone) {
558)     return; // invalid stone or rotation -> nothing to do
559)   }
560) 
561)   // add pixels to field
562)   for (int p = 0; p < c_pixelCnt; ++p) {
563)     int py = y + rotStone->pixels[p].y;
564)     int px = x + rotStone->pixels[p].x;
565)     if (checkLimitInt(py, 0, m_height - 1) &&
566)         checkLimitInt(px, 0, m_width - 1)) {
567)       int pi = py * m_width + px;
568)       m_field.at(pi) = stone; // mark pixel in field with stone index
569)     }
570)   }
571) }
572) 
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

573) /// draw a stone to image buffer
574) void Tetris::drawStone(int stone, int rot, int y, int x)
575) {
576)   colorStone(stone, rot, y, x, m_stoneColor);
577) }
578) 
579) /// wipe a stone from image buffer (i.e. replace it with background color)
580) void Tetris::wipeStone(int stone, int rot, int y, int x)
581) {
582)   colorStone(stone, rot, y, x, m_backgroundColor);
583) }
584) 
585) /// set shape of stone to color in image buffer
586) void Tetris::colorStone(int stone, int rot, int y, int x,
587)                         ColorData const &color)
588) {
589)   // get rotation of stone
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

592)     return; // invalid stone or rotation -> nothing to do
593)   }
594) 
595)   // color pixels
596)   for (int p = 0; p < c_pixelCnt; ++p) {
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

598)   }
599) }
600) 
601) /// stone data
602) Tetris::Stone const Tetris::c_stones[7] = {
603)   // the I
604)   { {
605)       { { { -2,  0 }, { -1,  0 }, {  0,  0 }, {  1,  0 } } },
606)       { { {  0, -2 }, {  0, -1 }, {  0,  0 }, {  0,  1 } } },
607)       { { { -2,  0 }, { -1,  0 }, {  0,  0 }, {  1,  0 } } },
608)       { { {  0, -2 }, {  0, -1 }, {  0,  0 }, {  0,  1 } } },
609)   } },
610)   // the L
611)   { {
612)       { { {  1, -1 }, { -1,  0 }, {  0,  0 }, {  1,  0 } } },
613)       { { {  0, -1 }, {  0,  0 }, {  0,  1 }, {  1,  1 } } },
614)       { { { -1,  0 }, {  0,  0 }, {  1,  0 }, { -1,  1 } } },
615)       { { { -1, -1 }, {  0, -1 }, {  0,  0 }, {  0,  1 } } },
616)   } },
617)   // the J
618)   { {
619)       { { { -1, -1 }, { -1,  0 }, {  0,  0 }, {  1,  0 } } },
620)       { { {  0, -1 }, {  1, -1 }, {  0,  0 }, {  0,  1 } } },
621)       { { { -1,  0 }, {  0,  0 }, {  1,  0 }, {  1,  1 } } },
622)       { { {  0, -1 }, {  0,  0 }, { -1,  1 }, {  0,  1 } } },
623)   } },
624)   // the T
625)   { {
626)       { { {  0, -1 }, { -1,  0 }, {  0,  0 }, {  1,  0 } } },
627)       { { {  0, -1 }, {  0,  0 }, {  1,  0 }, {  0,  1 } } },
628)       { { { -1,  0 }, {  0,  0 }, {  1,  0 }, {  0,  1 } } },
629)       { { {  0, -1 }, { -1,  0 }, {  0,  0 }, {  0,  1 } } },
630)   } },
631)   // the O
632)   { {
633)       { { {  0, -1 }, {  1, -1 }, {  0,  0 }, {  1,  0 } } },
634)       { { {  0, -1 }, {  1, -1 }, {  0,  0 }, {  1,  0 } } },
635)       { { {  0, -1 }, {  1, -1 }, {  0,  0 }, {  1,  0 } } },
636)       { { {  0, -1 }, {  1, -1 }, {  0,  0 }, {  1,  0 } } },
637)   } },
638)   // the Z
639)   { {
640)       { { { -1, -1 }, {  0, -1 }, {  0,  0 }, {  1,  0 } } },
641)       { { {  0, -1 }, { -1,  0 }, {  0,  0 }, { -1,  1 } } },
642)       { { { -1, -1 }, {  0, -1 }, {  0,  0 }, {  1,  0 } } },
643)       { { {  0, -1 }, { -1,  0 }, {  0,  0 }, { -1,  1 } } },
644)   } },
645)   // the S
646)   { {
647)       { { {  0, -1 }, {  1, -1 }, { -1,  0 }, {  0,  0 } } },
648)       { { { -1, -1 }, { -1,  0 }, {  0,  0 }, {  0,  1 } } },
649)       { { {  0, -1 }, {  1, -1 }, { -1,  0 }, {  0,  0 } } },
650)       { { { -1, -1 }, { -1,  0 }, {  0,  0 }, {  0,  1 } } },
651)   } },
652) };
653) 
654) /// number of stones
655) int const Tetris::c_stoneCnt = sizeof(Tetris::c_stones) /
656)                                sizeof(Tetris::c_stones[0]);
657) /// number of rotations per stone
658) int const Tetris::c_rotCnt = sizeof(Tetris::Stone::rot) /
659)                              sizeof(Tetris::Stone::rot[0]);
660) /// number of pixels per stone
661) int const Tetris::c_pixelCnt = sizeof(Tetris::RotStone::pixels) /
662)                                sizeof(Tetris::RotStone::pixels[0]);
663) 
664) /// descriptor for delay value
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

666) 
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

670) /// descriptor for delay value during blinking of disappearing rows
671) Tetris::ValueDescr const Tetris::c_blinkDelayDescr = { 50, 50, 250 };
672) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

673) /// descriptor for delay value at end of game
674) Tetris::ValueDescr const Tetris::c_gameOverDelayDescr = { 2000, 100, 5000 };
675)