92efc5f63475576cc9a8ee7702b2c63e6c47f03e
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),
Stefan Schuermans different colors for tetris...

Stefan Schuermans authored 5 years ago

39)   m_fileStoneIColor(dirBase.getFile("stoneIColor")),
40)   m_fileStoneLColor(dirBase.getFile("stoneLColor")),
41)   m_fileStoneJColor(dirBase.getFile("stoneJColor")),
42)   m_fileStoneTColor(dirBase.getFile("stoneTColor")),
43)   m_fileStoneOColor(dirBase.getFile("stoneOColor")),
44)   m_fileStoneZColor(dirBase.getFile("stoneZColor")),
45)   m_fileStoneSColor(dirBase.getFile("stoneSColor")),
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

46)   m_fileDelay(dirBase.getFile("delay")),
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

48)   m_fileBlinkDelay(dirBase.getFile("blinkDelay")),
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

53)   m_delay(c_delayDescr.default_),
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

58)   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

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

79) /**
80)  * @brief check for update of configuration (derived game)
81)  * @param[in,out] doReinit set to true to ask for reinitialization
82)  * @param[in,out] doRedraw set to true to ask for redrawing
83)  */
84) void Tetris::updateConfigGame(bool &doReinit, bool &doRedraw)
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)   (void)doReinit;
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

88)   // color file was modified -> convert color, ask for redraw
Stefan Schuermans use default colors when mis...

Stefan Schuermans authored 5 years ago

89)   if (colorUpdate(m_fileStoneIColor, 255, m_stoneColors[StoneI])) { doRedraw = true; }
90)   if (colorUpdate(m_fileStoneLColor, 255, m_stoneColors[StoneL])) { doRedraw = true; }
91)   if (colorUpdate(m_fileStoneJColor, 255, m_stoneColors[StoneJ])) { doRedraw = true; }
92)   if (colorUpdate(m_fileStoneTColor, 255, m_stoneColors[StoneT])) { doRedraw = true; }
93)   if (colorUpdate(m_fileStoneOColor, 255, m_stoneColors[StoneO])) { doRedraw = true; }
94)   if (colorUpdate(m_fileStoneZColor, 255, m_stoneColors[StoneZ])) { doRedraw = true; }
95)   if (colorUpdate(m_fileStoneSColor, 255, m_stoneColors[StoneS])) { doRedraw = true; }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

97)   // delay cfg value file was updated -> read new delay cfg value, no re-*
98)   valueUpdate(m_fileDelay, c_delayDescr, m_delay);
99)   valueUpdate(m_fileDropDelay, c_dropDelayDescr, m_dropDelay);
100)   valueUpdate(m_fileBlinkDelay, c_blinkDelayDescr, m_blinkDelay);
101)   valueUpdate(m_fileGameOverDelay, c_gameOverDelayDescr, m_gameOverDelay);
102) 
103)   // sound name file was modified -> re-read sound name, no reinit/draw needed
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

105)   soundUpdate(m_fileRowCompleteSound);
106)   soundUpdate(m_fileGameOverSound);
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

107) }
108) 
109) /**
110)  * @brief check if accepting new operator connection is possible
111)  * @param[in] name operator interface name
112)  * @return if accepting new connection is possible
113)  */
114) bool Tetris::acceptNewOpConn(const std::string &name)
115) {
116)   (void)name;
117) 
Stefan Schuermans add game interlock

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

120) }
121) 
122) /**
123)  * @brief new operator connection
124)  * @param[in] name operator interface name
125)  * @param[in] pConn operator connection object
126)  *
127)  * The new connection may not yet be used for sending inside this callback.
128)  */
129) void Tetris::newOpConn(const std::string &name, OpConn *pConn)
130) {
131)   (void)name;
132) 
133)   // player arrives and starts game
134)   if (! m_pConn) {
Stefan Schuermans add game interlock

Stefan Schuermans authored 5 years ago

135)     if (activate()) {
136)       m_pConn = pConn;
137)       requestOpConnSound(m_pConn, m_fileStartSound);
138)     } else {
139)       // activation failed (interlock), close connection as soon as possible
140)       requestOpConnClose(pConn);
141)     }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

142)   }
Stefan Schuermans add game interlock

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

144)   else {
145)     requestOpConnClose(pConn);
146)   }
147) }
148) 
149) /**
150)  * @brief key command received on operator connection
151)  * @param[in] pConn operator connection object
152)  * @param[in] key key that was pressed
153)  */
154) void Tetris::opConnRecvKey(OpConn *pConn, char key)
155) {
156)   // hash -> hang up
157)   if (key == '#') {
158)     opConnClose(pConn);
159)     pConn->close();
160)     return;
161)   }
162) 
163)   // star -> inform player about game
164)   if (key == '*') {
165)     playOpConnSound(pConn, m_fileStartSound);
166)     return;
167)   }
168) 
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

172)     return;
173)   }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

174) 
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

175)   // move left
176)   if (key == '4') {
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)   // move right
187)   if (key == '6') {
188)     if (checkStoneFit(m_stone, m_rot, m_posY, m_posX + 1)) {
189)       wipeStone(m_stone, m_rot, m_posY, m_posX);
190)       m_posX += 1;
191)       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

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

Stefan Schuermans authored 5 years ago

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

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

Stefan Schuermans authored 5 years ago

208)     }
209)     return;
210)   }
211) 
212)   // rotate right
213)   if (key == '2' || key == '3') {
214)     int new_rot = m_rot + 1;
215)     if (new_rot >= c_rotCnt) {
216)       new_rot = 0;
217)     }
218)     if (checkStoneFit(m_stone, new_rot, m_posY, m_posX)) {
219)       wipeStone(m_stone, m_rot, m_posY, m_posX);
220)       m_rot = new_rot;
221)       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

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

Stefan Schuermans authored 5 years ago

223)     }
224)     return;
225)   }
226) 
227)   // drop stone
228)   if (key == '8') {
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

229)     m_dropping = true;
Stefan Schuermans fix comment typo

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

231)     return;
232)   }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

233) }
234) 
235) /**
236)  * @brief play command received on operator connection
237)  * @param[in] pConn operator connection object
238)  * @param[in] sound name of sound to play
239)  */
240) void Tetris::opConnRecvPlay(OpConn *pConn, const std::string &sound)
241) {
242)   (void)pConn;
243)   (void)sound;
244) }
245) 
246) /**
247)  * @brief operator connection is closed
248)  * @param[in] pConn operator connection object
249)  *
250)  * The connection may not be used for sending any more in this callback.
251)  */
252) void Tetris::opConnClose(OpConn *pConn)
253) {
254)   // remove coperator connection from requests (if it was in)
255)   forgetOpConn(pConn);
256) 
257)   // player leaves -> deactivate game
258)   if (pConn == m_pConn) {
259)     m_pConn = NULL;
260)     deactivate();
261)   }
262) }
263) 
264) /// re-initialize game (e.g. due to config change)
265) void Tetris::reinitialize()
266) {
267)   // convert colors
Stefan Schuermans use default colors when mis...

Stefan Schuermans authored 5 years ago

268)   color2data(m_fileStoneIColor, 255, m_stoneColors[StoneI]);
269)   color2data(m_fileStoneLColor, 255, m_stoneColors[StoneL]);
270)   color2data(m_fileStoneJColor, 255, m_stoneColors[StoneJ]);
271)   color2data(m_fileStoneTColor, 255, m_stoneColors[StoneT]);
272)   color2data(m_fileStoneOColor, 255, m_stoneColors[StoneO]);
273)   color2data(m_fileStoneZColor, 255, m_stoneColors[StoneZ]);
274)   color2data(m_fileStoneSColor, 255, m_stoneColors[StoneS]);
Stefan Schuermans different colors for tetris...

Stefan Schuermans authored 5 years ago

275) 
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

276)   // get values
277)   valueFromFile(m_fileDelay, c_delayDescr, m_delay);
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

281) 
282)   // initialize field: empty
283)   m_field.clear();
284)   m_field.resize(m_height * m_width, -1);
285) 
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

286)   // initialize blinking rows: no row blinking
287)   m_rowsBlink.clear();
288)   m_rowsBlink.resize(m_height, false);
289) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

294) 
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

295)   // start with new stone
296)   newStone();
297) 
298)   // redraw image and send frame
299)   redraw();
300) 
301)   // request first time step if needed
302)   planTimeStep();
303) }
304) 
305) /// redraw current game image, expected to call sendFrame() at end
306) void Tetris::redraw()
307) {
308)   // draw background
309)   rectFill(0, m_height, 0, m_width, m_backgroundColor);
310) 
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

313)     if (! (m_blinking & 1) || ! m_rowsBlink.at(y)) {
314)       for (int x = 0; x < m_width; ++x, ++i) {
315)         if (m_field.at(i) >= 0) {
Stefan Schuermans different colors for tetris...

Stefan Schuermans authored 5 years ago

316)           pixel(y, x, m_stoneColors[m_field.at(i)]);
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

317)         }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

318)       }
319)     }
320)   }
321) 
322)   // draw current stone
323)   drawStone(m_stone, m_rot, m_posY, m_posX);
324) 
325)   // send updated image buffer as frame
326)   sendFrame();
327) }
328) 
329) /// process next time step of game
330) void Tetris::timeStep()
331) {
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

336)   } else if (m_blinking > 0) {
337)     timeBlinkRows();
338)   // falling stone
339)   } else {
340)     timeStone();
341)   }
342) 
343)   // request next time step
344)   planTimeStep();
345) }
346) 
347) /// count time at end of game
348) void Tetris::timeGameOver()
349) {
Stefan Schuermans tetris: one time step at ga...

Stefan Schuermans authored 5 years ago

350)   // close operator connection
351)   if (m_pConn) {
352)     forgetOpConn(m_pConn); // remove from requests (if it was in)
353)     m_pConn->close();
354)     m_pConn = NULL;
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

356) 
357)   // deactivate game
358)   deactivate();
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

359) }
360) 
361) /// blink completed rows
362) void Tetris::timeBlinkRows()
363) {
364)   // blink rows
365)   ++m_blinking;
366) 
367)   // end of blinking -> remove blinking rows, new stone
368)   if (m_blinking >= 8) {
369)     // remove blinking rows
370)     for (int b = 0; b < m_height; ++b) {
371)       if (m_rowsBlink.at(b)) {
372)         // move rows 0..b-1 one row down, i.e., to rows 1..b
373)         for (int y = b, i = b * m_width + m_width - 1; y > 0; --y) {
374)           for (int x = m_width - 1; x >= 0; --x, --i) {
375)             m_field.at(i) = m_field.at(i - m_width);
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

376)           }
377)         }
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

378)         // clear first row
379)         for (int x = 0; x < m_width; ++x) {
380)           m_field.at(x) = -1;
381)         }
382)         // row not blinking any more
383)         m_rowsBlink.at(b) = false;
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

384)       }
385)     }
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

386)     // blinking done
387)     m_blinking = 0;
388)     // new stone
389)     newStone();
390)   }
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

391) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

392)   // redraw image and send frame
393)   redraw();
394) }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

395) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

396) /// falling stone
397) void Tetris::timeStone()
398) {
399)   // stone can move down by one pixel
400)   if (checkStoneFit(m_stone, m_rot, m_posY + 1, m_posX)) {
401)     // move stone down by one pixel
402)     wipeStone(m_stone, m_rot, m_posY, m_posX);
403)     m_posY += 1;
404)     drawStone(m_stone, m_rot, m_posY, m_posX); // TODO: active color
405)   }
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

406) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

407)   // stone cannot move down by one pixel
408)   else {
409)     // add stone permanently to field at current position
410)     freezeStone(m_stone, m_rot, m_posY, m_posX);
411)     drawStone(m_stone, m_rot, m_posY, m_posX); // TODO: frozen color
412) 
413)     // overflow of game field -> game over
414)     if (checkStoneOverflow(m_stone, m_rot, m_posY, m_posX)) {
415)       // unset stone
416)       m_stone = -1;
417)       // game over
Stefan Schuermans tetris: one time step at ga...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

420)     }
421) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

423)     else {
424)       // no current stone any more
425)       m_stone = -1;
426)       // check for completed rows, (afterwards: new stone)
427)       checkComplete();
428)     }
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

429)   }
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

430) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

433) }
434) 
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

435) /// check for completed rows to disappear (new stone afterwards)
436) void Tetris::checkComplete()
437) {
438)   // collect y coordinated of completed rows -> m_rowsBlink
439)   bool blink = false;
440)   for (int y = 0, i = 0; y < m_height; ++y) {
441)     bool complete = true;
442)     for (int x = 0; x < m_width; ++x, ++i) {
443)       if (m_field.at(i) < 0) {
444)         complete = false;
445)       }
446)     }
447)     m_rowsBlink.at(y) = complete;
448)     if (complete) {
449)       blink = true;
450)     }
451)   }
452) 
453)   // no completed rows -> new stone
454)   if (! blink) {
455)     newStone();
456)   }
457) 
458)   // start blinking (start with rows visible, last bit == 0)
459)   else {
460)     m_blinking = 2;
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

462)   }
463) }
464) 
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

465) /// set up a new stone
466) void Tetris::newStone()
467) {
468)   // random stone, random rotation
469)   m_stone = rand() % c_stoneCnt;
470)   m_rot = rand() % c_rotCnt;
471) 
472)   // postion: two pixels above top middle
473)   m_posX = (m_width - 1) / 2;
474)   m_posY = -2;
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

475) 
476)   // stone is not being dropped yet
477)   m_dropping = false;
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

478) }
479) 
480) /// set time for next time step of game - or unset if not needed
481) void Tetris::planTimeStep()
482) {
483)   // no time call needed if not active
484)   if (! isActive()) {
485)     unsetTimeStep();
486)     return;
487)   }
488) 
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

493)     interval_ms = m_gameOverDelay;
494)     speedup = 0;
Stefan Schuermans tetris: add blink delay

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

499)   }
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

502) 
503)   // request next time call
504)   Time stepTime;
505)   stepTime.fromFloatSec(interval);
506)   setTimeStep(Time::now() + stepTime);
507) }
508) 
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

509) /// get rotatation of stone from stone/rotation index (or NULL in invalid)
510) Tetris::RotStone const * Tetris::getRotStone(int stone, int rot)
511) {
512)   if (! checkLimitInt(stone, 0, c_stoneCnt -1) ||
513)       ! checkLimitInt(rot, 0, c_rotCnt - 1)) {
514)     return NULL; // invalid stone or rotation
515)   }
516)   return &c_stones[stone].rot[rot];
517) }
518) 
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

519) /// check if stone fits at position
520) bool Tetris::checkStoneFit(int stone, int rot, int y, int x) const
521) {
522)   // get rotation of stone
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

525)     return false; // invalid stone or rotation -> does not fit
526)   }
527) 
528)   // check pixels
529)   for (int p = 0; p < c_pixelCnt; ++p) {
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

535)     if (py >= 0) { // do not check above top
536)       int pi = py * m_width + px;
537)       if (m_field.at(pi) >= 0) {
538)         return false; // occupixed pixel -> does not fit
539)       }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

540)     }
541)   }
542) 
543)   // all checks passed -> stone fits
544)   return true;
545) }
546) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

547) /// check if stone overflow game field
548) bool Tetris::checkStoneOverflow(int stone, int rot, int y, int x) const
549) {
550)   // get rotation of stone
551)   RotStone const *rotStone = getRotStone(stone, rot);
552)   if (! rotStone) {
553)     return true; // invalid stone or rotation -> overflow
554)   }
555) 
556)   // check pixels for overflow
557)   for (int p = 0; p < c_pixelCnt; ++p) {
558)     int py = y + rotStone->pixels[p].y;
559)     int px = x + rotStone->pixels[p].x;
560)     if (! checkLimitInt(py, 0, m_height -1) ||
561)         ! checkLimitInt(px, 0, m_width - 1)) {
562)       return true; // outside field (including top) -> overflow
563)     }
564)   }
565) 
566)   // all checks passed -> no overflow
567)   return false;
568) }
569) 
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

570) /// freeze stone to field at position
571) void Tetris::freezeStone(int stone, int rot, int y, int x)
572) {
573)   // get rotation of stone
574)   RotStone const *rotStone = getRotStone(stone, rot);
575)   if (! rotStone) {
576)     return; // invalid stone or rotation -> nothing to do
577)   }
578) 
579)   // add pixels to field
580)   for (int p = 0; p < c_pixelCnt; ++p) {
581)     int py = y + rotStone->pixels[p].y;
582)     int px = x + rotStone->pixels[p].x;
583)     if (checkLimitInt(py, 0, m_height - 1) &&
584)         checkLimitInt(px, 0, m_width - 1)) {
585)       int pi = py * m_width + px;
586)       m_field.at(pi) = stone; // mark pixel in field with stone index
587)     }
588)   }
589) }
590) 
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

591) /// draw a stone to image buffer
592) void Tetris::drawStone(int stone, int rot, int y, int x)
593) {
Stefan Schuermans different colors for tetris...

Stefan Schuermans authored 5 years ago

594)   colorStone(stone, rot, y, x, m_stoneColors[stone]);
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

595) }
596) 
597) /// wipe a stone from image buffer (i.e. replace it with background color)
598) void Tetris::wipeStone(int stone, int rot, int y, int x)
599) {
600)   colorStone(stone, rot, y, x, m_backgroundColor);
601) }
602) 
603) /// set shape of stone to color in image buffer
604) void Tetris::colorStone(int stone, int rot, int y, int x,
605)                         ColorData const &color)
606) {
607)   // get rotation of stone
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

610)     return; // invalid stone or rotation -> nothing to do
611)   }
612) 
613)   // color pixels
614)   for (int p = 0; p < c_pixelCnt; ++p) {
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

616)   }
617) }
618) 
Stefan Schuermans different colors for tetris...

Stefan Schuermans authored 5 years ago

619) /// stone data (make sure it matches the StoneIndex enum)
620) Tetris::Stone const Tetris::c_stones[Tetris::StoneCnt] = {
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

621)   // the I
622)   { {
623)       { { { -2,  0 }, { -1,  0 }, {  0,  0 }, {  1,  0 } } },
624)       { { {  0, -2 }, {  0, -1 }, {  0,  0 }, {  0,  1 } } },
625)       { { { -2,  0 }, { -1,  0 }, {  0,  0 }, {  1,  0 } } },
626)       { { {  0, -2 }, {  0, -1 }, {  0,  0 }, {  0,  1 } } },
627)   } },
628)   // the L
629)   { {
630)       { { {  1, -1 }, { -1,  0 }, {  0,  0 }, {  1,  0 } } },
631)       { { {  0, -1 }, {  0,  0 }, {  0,  1 }, {  1,  1 } } },
632)       { { { -1,  0 }, {  0,  0 }, {  1,  0 }, { -1,  1 } } },
633)       { { { -1, -1 }, {  0, -1 }, {  0,  0 }, {  0,  1 } } },
634)   } },
635)   // the J
636)   { {
637)       { { { -1, -1 }, { -1,  0 }, {  0,  0 }, {  1,  0 } } },
638)       { { {  0, -1 }, {  1, -1 }, {  0,  0 }, {  0,  1 } } },
639)       { { { -1,  0 }, {  0,  0 }, {  1,  0 }, {  1,  1 } } },
640)       { { {  0, -1 }, {  0,  0 }, { -1,  1 }, {  0,  1 } } },
641)   } },
642)   // the T
643)   { {
644)       { { {  0, -1 }, { -1,  0 }, {  0,  0 }, {  1,  0 } } },
645)       { { {  0, -1 }, {  0,  0 }, {  1,  0 }, {  0,  1 } } },
646)       { { { -1,  0 }, {  0,  0 }, {  1,  0 }, {  0,  1 } } },
647)       { { {  0, -1 }, { -1,  0 }, {  0,  0 }, {  0,  1 } } },
648)   } },
649)   // the O
650)   { {
651)       { { {  0, -1 }, {  1, -1 }, {  0,  0 }, {  1,  0 } } },
652)       { { {  0, -1 }, {  1, -1 }, {  0,  0 }, {  1,  0 } } },
653)       { { {  0, -1 }, {  1, -1 }, {  0,  0 }, {  1,  0 } } },
654)       { { {  0, -1 }, {  1, -1 }, {  0,  0 }, {  1,  0 } } },
655)   } },
656)   // the Z
657)   { {
658)       { { { -1, -1 }, {  0, -1 }, {  0,  0 }, {  1,  0 } } },
659)       { { {  0, -1 }, { -1,  0 }, {  0,  0 }, { -1,  1 } } },
660)       { { { -1, -1 }, {  0, -1 }, {  0,  0 }, {  1,  0 } } },
661)       { { {  0, -1 }, { -1,  0 }, {  0,  0 }, { -1,  1 } } },
662)   } },
663)   // the S
664)   { {
665)       { { {  0, -1 }, {  1, -1 }, { -1,  0 }, {  0,  0 } } },
666)       { { { -1, -1 }, { -1,  0 }, {  0,  0 }, {  0,  1 } } },
667)       { { {  0, -1 }, {  1, -1 }, { -1,  0 }, {  0,  0 } } },
668)       { { { -1, -1 }, { -1,  0 }, {  0,  0 }, {  0,  1 } } },
669)   } },
670) };
671) 
672) /// number of stones
673) int const Tetris::c_stoneCnt = sizeof(Tetris::c_stones) /
674)                                sizeof(Tetris::c_stones[0]);
675) /// number of rotations per stone
676) int const Tetris::c_rotCnt = sizeof(Tetris::Stone::rot) /
677)                              sizeof(Tetris::Stone::rot[0]);
678) /// number of pixels per stone
679) int const Tetris::c_pixelCnt = sizeof(Tetris::RotStone::pixels) /
680)                                sizeof(Tetris::RotStone::pixels[0]);
681) 
682) /// descriptor for delay value
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

684) 
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

691) /// descriptor for delay value at end of game
692) Tetris::ValueDescr const Tetris::c_gameOverDelayDescr = { 2000, 100, 5000 };
693)