e897205a2f2e4ef710f8b48d0a3b8c7e93cd8632
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) 
107)   // accept player if no one there yet
108)   return ! m_pConn;
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) {
124)     m_pConn = pConn;
125)     requestOpConnSound(m_pConn, m_fileStartSound);
126)     activate();
127)   }
128)   // close imcoming connection as soon as possible, nothing else happens
129)   else {
130)     requestOpConnClose(pConn);
131)     return;
132)   }
133) }
134) 
135) /**
136)  * @brief key command received on operator connection
137)  * @param[in] pConn operator connection object
138)  * @param[in] key key that was pressed
139)  */
140) void Tetris::opConnRecvKey(OpConn *pConn, char key)
141) {
142)   // hash -> hang up
143)   if (key == '#') {
144)     opConnClose(pConn);
145)     pConn->close();
146)     return;
147)   }
148) 
149)   // star -> inform player about game
150)   if (key == '*') {
151)     playOpConnSound(pConn, m_fileStartSound);
152)     return;
153)   }
154) 
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

158)     return;
159)   }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

160) 
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

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

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

Stefan Schuermans authored 5 years ago

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

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

Stefan Schuermans authored 5 years ago

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

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

Stefan Schuermans authored 5 years ago

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

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

217)     return;
218)   }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

273) 
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

335) 
336)   // deactivate game
337)   deactivate();
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

355)           }
356)         }
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

363)       }
364)     }
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

365)     // blinking done
366)     m_blinking = 0;
367)     // new stone
368)     newStone();
369)   }
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

370) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

371)   // redraw image and send frame
372)   redraw();
373) }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

374) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

385) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

399)     }
400) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

408)   }
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

409) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

412) }
413) 
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

441)   }
442) }
443) 
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

454) 
455)   // stone is not being dropped yet
456)   m_dropping = false;
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

472)     interval_ms = m_gameOverDelay;
473)     speedup = 0;
Stefan Schuermans tetris: add blink delay

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

478)   }
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

663) 
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

670) /// descriptor for delay value at end of game
671) Tetris::ValueDescr const Tetris::c_gameOverDelayDescr = { 2000, 100, 5000 };
672)