20c513cbd3d59f5262f4c3f17b57c9b50e00b66f
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) 
74) /// check for update of configuration (derived game), return true on update
75) bool Tetris::updateConfigGame()
76) {
77)   bool ret = false;
78) 
79)   // color file was modified -> convert color, return true for update
80)   // cfg value file was updated -> read new cfg value, return true for update
Stefan Schuermans tetris: always check all co...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

91)     ret = true;
92)   }
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

93)   if (valueUpdate(m_fileGameOverDelay, c_gameOverDelayDescr,
94)                   m_gameOverDelay)) {
95)     ret = true;
96)   }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

97) 
98)   // sound name file was modified -> re-read sound name, no other update needed
99)   soundUpdate(m_fileStartSound);
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

100)   soundUpdate(m_fileRowCompleteSound);
101)   soundUpdate(m_fileGameOverSound);
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

166)     return;
167)   }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

168) 
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

169)   // move left
170)   if (key == '4') {
171)     if (checkStoneFit(m_stone, m_rot, m_posY, m_posX - 1)) {
172)       wipeStone(m_stone, m_rot, m_posY, m_posX);
173)       m_posX -= 1;
174)       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

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

Stefan Schuermans authored 5 years ago

176)     }
177)     return;
178)   }
179) 
180)   // move right
181)   if (key == '6') {
182)     if (checkStoneFit(m_stone, m_rot, m_posY, m_posX + 1)) {
183)       wipeStone(m_stone, m_rot, m_posY, m_posX);
184)       m_posX += 1;
185)       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

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

Stefan Schuermans authored 5 years ago

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

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

Stefan Schuermans authored 5 years ago

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

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

Stefan Schuermans authored 5 years ago

217)     }
218)     return;
219)   }
220) 
221)   // drop stone
222)   if (key == '8') {
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

225)     return;
226)   }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

268) 
269)   // initialize field: empty
270)   m_field.clear();
271)   m_field.resize(m_height * m_width, -1);
272) 
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

273)   // initialize blinking rows: no row blinking
274)   m_rowsBlink.clear();
275)   m_rowsBlink.resize(m_height, false);
276) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

281) 
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

300)     if (! (m_blinking & 1) || ! m_rowsBlink.at(y)) {
301)       for (int x = 0; x < m_width; ++x, ++i) {
302)         if (m_field.at(i) >= 0) {
303)           pixel(y, x, m_stoneColor);
304)         }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

337)   // close operator connection
338)   if (m_pConn) {
339)     forgetOpConn(m_pConn); // remove from requests (if it was in)
340)     m_pConn->close();
341)     m_pConn = NULL;
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

343) 
344)   // deactivate game
345)   deactivate();
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

346) }
347) 
348) /// blink completed rows
349) void Tetris::timeBlinkRows()
350) {
351)   // blink rows
352)   ++m_blinking;
353) 
354)   // end of blinking -> remove blinking rows, new stone
355)   if (m_blinking >= 8) {
356)     // remove blinking rows
357)     for (int b = 0; b < m_height; ++b) {
358)       if (m_rowsBlink.at(b)) {
359)         // move rows 0..b-1 one row down, i.e., to rows 1..b
360)         for (int y = b, i = b * m_width + m_width - 1; y > 0; --y) {
361)           for (int x = m_width - 1; x >= 0; --x, --i) {
362)             m_field.at(i) = m_field.at(i - m_width);
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)         // clear first row
366)         for (int x = 0; x < m_width; ++x) {
367)           m_field.at(x) = -1;
368)         }
369)         // row not blinking any more
370)         m_rowsBlink.at(b) = false;
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

371)       }
372)     }
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

373)     // blinking done
374)     m_blinking = 0;
375)     // new stone
376)     newStone();
377)   }
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

378) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

379)   // redraw image and send frame
380)   redraw();
381) }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

382) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

393) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

407)     }
408) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

410)     else {
411)       // no current stone any more
412)       m_stone = -1;
413)       // check for completed rows, (afterwards: new stone)
414)       checkComplete();
415)     }
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

416)   }
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

417) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

420) }
421) 
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

449)   }
450) }
451) 
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

462) 
463)   // stone is not being dropped yet
464)   m_dropping = false;
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

480)     interval_ms = m_gameOverDelay;
481)     speedup = 0;
Stefan Schuermans tetris: add blink delay

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

486)   }
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

489) 
490)   // request next time call
491)   Time stepTime;
492)   stepTime.fromFloatSec(interval);
493)   setTimeStep(Time::now() + stepTime);
494) }
495) 
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

506) /// check if stone fits at position
507) bool Tetris::checkStoneFit(int stone, int rot, int y, int x) const
508) {
509)   // get rotation of stone
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

512)     return false; // invalid stone or rotation -> does not fit
513)   }
514) 
515)   // check pixels
516)   for (int p = 0; p < c_pixelCnt; ++p) {
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

522)     if (py >= 0) { // do not check above top
523)       int pi = py * m_width + px;
524)       if (m_field.at(pi) >= 0) {
525)         return false; // occupixed pixel -> does not fit
526)       }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

527)     }
528)   }
529) 
530)   // all checks passed -> stone fits
531)   return true;
532) }
533) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

597)     return; // invalid stone or rotation -> nothing to do
598)   }
599) 
600)   // color pixels
601)   for (int p = 0; p < c_pixelCnt; ++p) {
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

671) 
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

678) /// descriptor for delay value at end of game
679) Tetris::ValueDescr const Tetris::c_gameOverDelayDescr = { 2000, 100, 5000 };
680)