44109b7871052839bdfbcd20bb3e77315154a866
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 make tetris stones change c...

Stefan Schuermans authored 5 years ago

46)   m_fileFixedIColor(dirBase.getFile("fixedIColor")),
47)   m_fileFixedLColor(dirBase.getFile("fixedLColor")),
48)   m_fileFixedJColor(dirBase.getFile("fixedJColor")),
49)   m_fileFixedTColor(dirBase.getFile("fixedTColor")),
50)   m_fileFixedOColor(dirBase.getFile("fixedOColor")),
51)   m_fileFixedZColor(dirBase.getFile("fixedZColor")),
52)   m_fileFixedSColor(dirBase.getFile("fixedSColor")),
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

68) {
69)   // open operator connection interfaces for player
70)   m_mgrs.m_opMgr.open(m_name, this);
71) }
72) 
73) /// virtual destructor
74) Tetris::~Tetris()
75) {
76)   // close operator connection interface
77)   m_mgrs.m_opMgr.close(m_name);
78) 
79)   // close open operator connection
80)   if (m_pConn) {
81)     m_pConn->close();
82)     m_pConn = NULL;
83)   }
84) }
85) 
Stefan Schuermans change of some game params...

Stefan Schuermans authored 5 years ago

86) /**
87)  * @brief check for update of configuration (derived game)
88)  * @param[in,out] doReinit set to true to ask for reinitialization
89)  * @param[in,out] doRedraw set to true to ask for redrawing
90)  */
91) void Tetris::updateConfigGame(bool &doReinit, bool &doRedraw)
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

95)   // color file was modified -> convert color, ask for redraw
Stefan Schuermans make tetris stones change c...

Stefan Schuermans authored 5 years ago

96)   if (colorUpdate(m_fileStoneIColor, 255, m_stoneColors[Active][StoneI])) {
97)     doRedraw = true;
98)   }
99)   if (colorUpdate(m_fileStoneLColor, 255, m_stoneColors[Active][StoneL])) {
100)     doRedraw = true;
101)   }
102)   if (colorUpdate(m_fileStoneJColor, 255, m_stoneColors[Active][StoneJ])) {
103)     doRedraw = true;
104)   }
105)   if (colorUpdate(m_fileStoneTColor, 255, m_stoneColors[Active][StoneT])) {
106)     doRedraw = true;
107)   }
108)   if (colorUpdate(m_fileStoneOColor, 255, m_stoneColors[Active][StoneO])) {
109)     doRedraw = true;
110)   }
111)   if (colorUpdate(m_fileStoneZColor, 255, m_stoneColors[Active][StoneZ])) {
112)     doRedraw = true;
113)   }
114)   if (colorUpdate(m_fileStoneSColor, 255, m_stoneColors[Active][StoneS])) {
115)     doRedraw = true;
116)   }
117)   if (colorUpdate(m_fileFixedIColor, 192, m_stoneColors[Fixed][StoneI])) {
118)     doRedraw = true;
119)   }
120)   if (colorUpdate(m_fileFixedLColor, 192, m_stoneColors[Fixed][StoneL])) {
121)     doRedraw = true;
122)   }
123)   if (colorUpdate(m_fileFixedJColor, 192, m_stoneColors[Fixed][StoneJ])) {
124)     doRedraw = true;
125)   }
126)   if (colorUpdate(m_fileFixedTColor, 192, m_stoneColors[Fixed][StoneT])) {
127)     doRedraw = true;
128)   }
129)   if (colorUpdate(m_fileFixedOColor, 192, m_stoneColors[Fixed][StoneO])) {
130)     doRedraw = true;
131)   }
132)   if (colorUpdate(m_fileFixedZColor, 192, m_stoneColors[Fixed][StoneZ])) {
133)     doRedraw = true;
134)   }
135)   if (colorUpdate(m_fileFixedSColor, 192, m_stoneColors[Fixed][StoneS])) {
136)     doRedraw = true;
137)   }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

139)   // delay cfg value file was updated -> read new delay cfg value, no re-*
140)   valueUpdate(m_fileDelay, c_delayDescr, m_delay);
141)   valueUpdate(m_fileDropDelay, c_dropDelayDescr, m_dropDelay);
142)   valueUpdate(m_fileBlinkDelay, c_blinkDelayDescr, m_blinkDelay);
143)   valueUpdate(m_fileGameOverDelay, c_gameOverDelayDescr, m_gameOverDelay);
144) 
145)   // sound name file was modified -> re-read sound name, no reinit/draw needed
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

147)   soundUpdate(m_fileRowCompleteSound);
148)   soundUpdate(m_fileGameOverSound);
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

149) }
150) 
151) /**
152)  * @brief check if accepting new operator connection is possible
153)  * @param[in] name operator interface name
154)  * @return if accepting new connection is possible
155)  */
156) bool Tetris::acceptNewOpConn(const std::string &name)
157) {
158)   (void)name;
159) 
Stefan Schuermans add game interlock

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

162) }
163) 
164) /**
165)  * @brief new operator connection
166)  * @param[in] name operator interface name
167)  * @param[in] pConn operator connection object
168)  *
169)  * The new connection may not yet be used for sending inside this callback.
170)  */
171) void Tetris::newOpConn(const std::string &name, OpConn *pConn)
172) {
173)   (void)name;
174) 
175)   // player arrives and starts game
176)   if (! m_pConn) {
Stefan Schuermans add game interlock

Stefan Schuermans authored 5 years ago

177)     if (activate()) {
178)       m_pConn = pConn;
179)       requestOpConnSound(m_pConn, m_fileStartSound);
180)     } else {
181)       // activation failed (interlock), close connection as soon as possible
182)       requestOpConnClose(pConn);
183)     }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

184)   }
Stefan Schuermans add game interlock

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

186)   else {
187)     requestOpConnClose(pConn);
188)   }
189) }
190) 
191) /**
192)  * @brief key command received on operator connection
193)  * @param[in] pConn operator connection object
194)  * @param[in] key key that was pressed
195)  */
196) void Tetris::opConnRecvKey(OpConn *pConn, char key)
197) {
198)   // hash -> hang up
199)   if (key == '#') {
200)     opConnClose(pConn);
201)     pConn->close();
202)     return;
203)   }
204) 
205)   // star -> inform player about game
206)   if (key == '*') {
207)     playOpConnSound(pConn, m_fileStartSound);
208)     return;
209)   }
210) 
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

216) 
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

217)   // move left
218)   if (key == '4') {
219)     if (checkStoneFit(m_stone, m_rot, m_posY, m_posX - 1)) {
220)       wipeStone(m_stone, m_rot, m_posY, m_posX);
221)       m_posX -= 1;
Stefan Schuermans make tetris stones change c...

Stefan Schuermans authored 5 years ago

222)       drawStone(m_stone, m_rot, m_posY, m_posX, Active);
Stefan Schuermans tetris: output frame on sto...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

224)     }
225)     return;
226)   }
227) 
228)   // move right
229)   if (key == '6') {
230)     if (checkStoneFit(m_stone, m_rot, m_posY, m_posX + 1)) {
231)       wipeStone(m_stone, m_rot, m_posY, m_posX);
232)       m_posX += 1;
Stefan Schuermans make tetris stones change c...

Stefan Schuermans authored 5 years ago

233)       drawStone(m_stone, m_rot, m_posY, m_posX, Active);
Stefan Schuermans tetris: output frame on sto...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

235)     }
236)     return;
237)   }
238) 
239)   // rotate left
240)   if (key == '1') {
241)     int new_rot = m_rot - 1;
242)     if (new_rot < 0) {
243)       new_rot = c_rotCnt - 1;
244)     }
245)     if (checkStoneFit(m_stone, new_rot, m_posY, m_posX)) {
246)       wipeStone(m_stone, m_rot, m_posY, m_posX);
247)       m_rot = new_rot;
Stefan Schuermans make tetris stones change c...

Stefan Schuermans authored 5 years ago

248)       drawStone(m_stone, m_rot, m_posY, m_posX, Active);
Stefan Schuermans tetris: output frame on sto...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

250)     }
251)     return;
252)   }
253) 
254)   // rotate right
255)   if (key == '2' || key == '3') {
256)     int new_rot = m_rot + 1;
257)     if (new_rot >= c_rotCnt) {
258)       new_rot = 0;
259)     }
260)     if (checkStoneFit(m_stone, new_rot, m_posY, m_posX)) {
261)       wipeStone(m_stone, m_rot, m_posY, m_posX);
262)       m_rot = new_rot;
Stefan Schuermans make tetris stones change c...

Stefan Schuermans authored 5 years ago

263)       drawStone(m_stone, m_rot, m_posY, m_posX, Active);
Stefan Schuermans tetris: output frame on sto...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

265)     }
266)     return;
267)   }
268) 
269)   // drop stone
270)   if (key == '8') {
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

271)     m_dropping = true;
Stefan Schuermans fix comment typo

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

273)     return;
274)   }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

275) }
276) 
277) /**
278)  * @brief play command received on operator connection
279)  * @param[in] pConn operator connection object
280)  * @param[in] sound name of sound to play
281)  */
282) void Tetris::opConnRecvPlay(OpConn *pConn, const std::string &sound)
283) {
284)   (void)pConn;
285)   (void)sound;
286) }
287) 
288) /**
289)  * @brief operator connection is closed
290)  * @param[in] pConn operator connection object
291)  *
292)  * The connection may not be used for sending any more in this callback.
293)  */
294) void Tetris::opConnClose(OpConn *pConn)
295) {
296)   // remove coperator connection from requests (if it was in)
297)   forgetOpConn(pConn);
298) 
299)   // player leaves -> deactivate game
300)   if (pConn == m_pConn) {
301)     m_pConn = NULL;
302)     deactivate();
303)   }
304) }
305) 
306) /// re-initialize game (e.g. due to config change)
307) void Tetris::reinitialize()
308) {
309)   // convert colors
Stefan Schuermans make tetris stones change c...

Stefan Schuermans authored 5 years ago

310)   color2data(m_fileStoneIColor, 255, m_stoneColors[Active][StoneI]);
311)   color2data(m_fileStoneLColor, 255, m_stoneColors[Active][StoneL]);
312)   color2data(m_fileStoneJColor, 255, m_stoneColors[Active][StoneJ]);
313)   color2data(m_fileStoneTColor, 255, m_stoneColors[Active][StoneT]);
314)   color2data(m_fileStoneOColor, 255, m_stoneColors[Active][StoneO]);
315)   color2data(m_fileStoneZColor, 255, m_stoneColors[Active][StoneZ]);
316)   color2data(m_fileStoneSColor, 255, m_stoneColors[Active][StoneS]);
317)   color2data(m_fileFixedIColor, 255, m_stoneColors[Fixed][StoneI]);
318)   color2data(m_fileFixedLColor, 255, m_stoneColors[Fixed][StoneL]);
319)   color2data(m_fileFixedJColor, 255, m_stoneColors[Fixed][StoneJ]);
320)   color2data(m_fileFixedTColor, 255, m_stoneColors[Fixed][StoneT]);
321)   color2data(m_fileFixedOColor, 255, m_stoneColors[Fixed][StoneO]);
322)   color2data(m_fileFixedZColor, 255, m_stoneColors[Fixed][StoneZ]);
323)   color2data(m_fileFixedSColor, 255, m_stoneColors[Fixed][StoneS]);
Stefan Schuermans different colors for tetris...

Stefan Schuermans authored 5 years ago

324) 
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

330) 
331)   // initialize field: empty
332)   m_field.clear();
333)   m_field.resize(m_height * m_width, -1);
334) 
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

335)   // initialize blinking rows: no row blinking
336)   m_rowsBlink.clear();
337)   m_rowsBlink.resize(m_height, false);
338) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

343) 
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

344)   // start with new stone
345)   newStone();
346) 
347)   // redraw image and send frame
348)   redraw();
349) 
350)   // request first time step if needed
351)   planTimeStep();
352) }
353) 
354) /// redraw current game image, expected to call sendFrame() at end
355) void Tetris::redraw()
356) {
357)   // draw background
358)   rectFill(0, m_height, 0, m_width, m_backgroundColor);
359) 
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

362)     if (! (m_blinking & 1) || ! m_rowsBlink.at(y)) {
363)       for (int x = 0; x < m_width; ++x, ++i) {
364)         if (m_field.at(i) >= 0) {
Stefan Schuermans make tetris stones change c...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

366)         }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

367)       }
368)     }
369)   }
370) 
371)   // draw current stone
Stefan Schuermans make tetris stones change c...

Stefan Schuermans authored 5 years ago

372)   drawStone(m_stone, m_rot, m_posY, m_posX, Active);
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

373) 
374)   // send updated image buffer as frame
375)   sendFrame();
376) }
377) 
378) /// process next time step of game
379) void Tetris::timeStep()
380) {
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

385)   } else if (m_blinking > 0) {
386)     timeBlinkRows();
387)   // falling stone
388)   } else {
389)     timeStone();
390)   }
391) 
392)   // request next time step
393)   planTimeStep();
394) }
395) 
396) /// count time at end of game
397) void Tetris::timeGameOver()
398) {
Stefan Schuermans tetris: one time step at ga...

Stefan Schuermans authored 5 years ago

399)   // close operator connection
400)   if (m_pConn) {
401)     forgetOpConn(m_pConn); // remove from requests (if it was in)
402)     m_pConn->close();
403)     m_pConn = NULL;
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

405) 
406)   // deactivate game
407)   deactivate();
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

408) }
409) 
410) /// blink completed rows
411) void Tetris::timeBlinkRows()
412) {
413)   // blink rows
414)   ++m_blinking;
415) 
416)   // end of blinking -> remove blinking rows, new stone
417)   if (m_blinking >= 8) {
418)     // remove blinking rows
419)     for (int b = 0; b < m_height; ++b) {
420)       if (m_rowsBlink.at(b)) {
421)         // move rows 0..b-1 one row down, i.e., to rows 1..b
422)         for (int y = b, i = b * m_width + m_width - 1; y > 0; --y) {
423)           for (int x = m_width - 1; x >= 0; --x, --i) {
424)             m_field.at(i) = m_field.at(i - m_width);
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

425)           }
426)         }
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

427)         // clear first row
428)         for (int x = 0; x < m_width; ++x) {
429)           m_field.at(x) = -1;
430)         }
431)         // row not blinking any more
432)         m_rowsBlink.at(b) = false;
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

433)       }
434)     }
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

435)     // blinking done
436)     m_blinking = 0;
437)     // new stone
438)     newStone();
439)   }
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

440) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

441)   // redraw image and send frame
442)   redraw();
443) }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

444) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

445) /// falling stone
446) void Tetris::timeStone()
447) {
448)   // stone can move down by one pixel
449)   if (checkStoneFit(m_stone, m_rot, m_posY + 1, m_posX)) {
450)     // move stone down by one pixel
451)     wipeStone(m_stone, m_rot, m_posY, m_posX);
452)     m_posY += 1;
Stefan Schuermans make tetris stones change c...

Stefan Schuermans authored 5 years ago

453)     drawStone(m_stone, m_rot, m_posY, m_posX, Active);
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

454)   }
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

455) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

456)   // stone cannot move down by one pixel
457)   else {
458)     // add stone permanently to field at current position
459)     freezeStone(m_stone, m_rot, m_posY, m_posX);
Stefan Schuermans make tetris stones change c...

Stefan Schuermans authored 5 years ago

460)     drawStone(m_stone, m_rot, m_posY, m_posX, Fixed);
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

461) 
462)     // overflow of game field -> game over
463)     if (checkStoneOverflow(m_stone, m_rot, m_posY, m_posX)) {
464)       // unset stone
465)       m_stone = -1;
466)       // game over
Stefan Schuermans tetris: one time step at ga...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

469)     }
470) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

472)     else {
473)       // no current stone any more
474)       m_stone = -1;
475)       // check for completed rows, (afterwards: new stone)
476)       checkComplete();
477)     }
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

478)   }
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

479) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

482) }
483) 
Stefan Schuermans tetris: remove completed rows

Stefan Schuermans authored 5 years ago

484) /// check for completed rows to disappear (new stone afterwards)
485) void Tetris::checkComplete()
486) {
487)   // collect y coordinated of completed rows -> m_rowsBlink
488)   bool blink = false;
489)   for (int y = 0, i = 0; y < m_height; ++y) {
490)     bool complete = true;
491)     for (int x = 0; x < m_width; ++x, ++i) {
492)       if (m_field.at(i) < 0) {
493)         complete = false;
494)       }
495)     }
496)     m_rowsBlink.at(y) = complete;
497)     if (complete) {
498)       blink = true;
499)     }
500)   }
501) 
502)   // no completed rows -> new stone
503)   if (! blink) {
504)     newStone();
505)   }
506) 
507)   // start blinking (start with rows visible, last bit == 0)
508)   else {
509)     m_blinking = 2;
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

511)   }
512) }
513) 
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

514) /// set up a new stone
515) void Tetris::newStone()
516) {
517)   // random stone, random rotation
518)   m_stone = rand() % c_stoneCnt;
519)   m_rot = rand() % c_rotCnt;
520) 
521)   // postion: two pixels above top middle
522)   m_posX = (m_width - 1) / 2;
523)   m_posY = -2;
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

524) 
525)   // stone is not being dropped yet
526)   m_dropping = false;
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

527) }
528) 
529) /// set time for next time step of game - or unset if not needed
530) void Tetris::planTimeStep()
531) {
532)   // no time call needed if not active
533)   if (! isActive()) {
534)     unsetTimeStep();
535)     return;
536)   }
537) 
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

542)     interval_ms = m_gameOverDelay;
543)     speedup = 0;
Stefan Schuermans tetris: add blink delay

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

548)   }
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

551) 
552)   // request next time call
553)   Time stepTime;
554)   stepTime.fromFloatSec(interval);
555)   setTimeStep(Time::now() + stepTime);
556) }
557) 
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

558) /// get rotatation of stone from stone/rotation index (or NULL in invalid)
559) Tetris::RotStone const * Tetris::getRotStone(int stone, int rot)
560) {
561)   if (! checkLimitInt(stone, 0, c_stoneCnt -1) ||
562)       ! checkLimitInt(rot, 0, c_rotCnt - 1)) {
563)     return NULL; // invalid stone or rotation
564)   }
565)   return &c_stones[stone].rot[rot];
566) }
567) 
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

568) /// check if stone fits at position
569) bool Tetris::checkStoneFit(int stone, int rot, int y, int x) const
570) {
571)   // get rotation of stone
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

574)     return false; // invalid stone or rotation -> does not fit
575)   }
576) 
577)   // check pixels
578)   for (int p = 0; p < c_pixelCnt; ++p) {
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

584)     if (py >= 0) { // do not check above top
585)       int pi = py * m_width + px;
586)       if (m_field.at(pi) >= 0) {
587)         return false; // occupixed pixel -> does not fit
588)       }
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

589)     }
590)   }
591) 
592)   // all checks passed -> stone fits
593)   return true;
594) }
595) 
Stefan Schuermans tetris: complete game logic

Stefan Schuermans authored 5 years ago

596) /// check if stone overflow game field
597) bool Tetris::checkStoneOverflow(int stone, int rot, int y, int x) const
598) {
599)   // get rotation of stone
600)   RotStone const *rotStone = getRotStone(stone, rot);
601)   if (! rotStone) {
602)     return true; // invalid stone or rotation -> overflow
603)   }
604) 
605)   // check pixels for overflow
606)   for (int p = 0; p < c_pixelCnt; ++p) {
607)     int py = y + rotStone->pixels[p].y;
608)     int px = x + rotStone->pixels[p].x;
609)     if (! checkLimitInt(py, 0, m_height -1) ||
610)         ! checkLimitInt(px, 0, m_width - 1)) {
611)       return true; // outside field (including top) -> overflow
612)     }
613)   }
614) 
615)   // all checks passed -> no overflow
616)   return false;
617) }
618) 
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

619) /// freeze stone to field at position
620) void Tetris::freezeStone(int stone, int rot, int y, int x)
621) {
622)   // get rotation of stone
623)   RotStone const *rotStone = getRotStone(stone, rot);
624)   if (! rotStone) {
625)     return; // invalid stone or rotation -> nothing to do
626)   }
627) 
628)   // add pixels to field
629)   for (int p = 0; p < c_pixelCnt; ++p) {
630)     int py = y + rotStone->pixels[p].y;
631)     int px = x + rotStone->pixels[p].x;
632)     if (checkLimitInt(py, 0, m_height - 1) &&
633)         checkLimitInt(px, 0, m_width - 1)) {
634)       int pi = py * m_width + px;
635)       m_field.at(pi) = stone; // mark pixel in field with stone index
636)     }
637)   }
638) }
639) 
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

640) /// draw a stone to image buffer
Stefan Schuermans make tetris stones change c...

Stefan Schuermans authored 5 years ago

641) void Tetris::drawStone(int stone, int rot, int y, int x, State state)
Stefan Schuermans tetris game WIP

Stefan Schuermans authored 5 years ago

642) {
Stefan Schuermans make tetris stones change c...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

644) }
645) 
646) /// wipe a stone from image buffer (i.e. replace it with background color)
647) void Tetris::wipeStone(int stone, int rot, int y, int x)
648) {
649)   colorStone(stone, rot, y, x, m_backgroundColor);
650) }
651) 
652) /// set shape of stone to color in image buffer
653) void Tetris::colorStone(int stone, int rot, int y, int x,
654)                         ColorData const &color)
655) {
656)   // get rotation of stone
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

659)     return; // invalid stone or rotation -> nothing to do
660)   }
661) 
662)   // color pixels
663)   for (int p = 0; p < c_pixelCnt; ++p) {
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

665)   }
666) }
667) 
Stefan Schuermans different colors for tetris...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

670)   // the I
671)   { {
672)       { { { -2,  0 }, { -1,  0 }, {  0,  0 }, {  1,  0 } } },
673)       { { {  0, -2 }, {  0, -1 }, {  0,  0 }, {  0,  1 } } },
674)       { { { -2,  0 }, { -1,  0 }, {  0,  0 }, {  1,  0 } } },
675)       { { {  0, -2 }, {  0, -1 }, {  0,  0 }, {  0,  1 } } },
676)   } },
677)   // the L
678)   { {
679)       { { {  1, -1 }, { -1,  0 }, {  0,  0 }, {  1,  0 } } },
680)       { { {  0, -1 }, {  0,  0 }, {  0,  1 }, {  1,  1 } } },
681)       { { { -1,  0 }, {  0,  0 }, {  1,  0 }, { -1,  1 } } },
682)       { { { -1, -1 }, {  0, -1 }, {  0,  0 }, {  0,  1 } } },
683)   } },
684)   // the J
685)   { {
686)       { { { -1, -1 }, { -1,  0 }, {  0,  0 }, {  1,  0 } } },
687)       { { {  0, -1 }, {  1, -1 }, {  0,  0 }, {  0,  1 } } },
688)       { { { -1,  0 }, {  0,  0 }, {  1,  0 }, {  1,  1 } } },
689)       { { {  0, -1 }, {  0,  0 }, { -1,  1 }, {  0,  1 } } },
690)   } },
691)   // the T
692)   { {
693)       { { {  0, -1 }, { -1,  0 }, {  0,  0 }, {  1,  0 } } },
694)       { { {  0, -1 }, {  0,  0 }, {  1,  0 }, {  0,  1 } } },
695)       { { { -1,  0 }, {  0,  0 }, {  1,  0 }, {  0,  1 } } },
696)       { { {  0, -1 }, { -1,  0 }, {  0,  0 }, {  0,  1 } } },
697)   } },
698)   // the O
699)   { {
700)       { { {  0, -1 }, {  1, -1 }, {  0,  0 }, {  1,  0 } } },
701)       { { {  0, -1 }, {  1, -1 }, {  0,  0 }, {  1,  0 } } },
702)       { { {  0, -1 }, {  1, -1 }, {  0,  0 }, {  1,  0 } } },
703)       { { {  0, -1 }, {  1, -1 }, {  0,  0 }, {  1,  0 } } },
704)   } },
705)   // the Z
706)   { {
707)       { { { -1, -1 }, {  0, -1 }, {  0,  0 }, {  1,  0 } } },
708)       { { {  0, -1 }, { -1,  0 }, {  0,  0 }, { -1,  1 } } },
709)       { { { -1, -1 }, {  0, -1 }, {  0,  0 }, {  1,  0 } } },
710)       { { {  0, -1 }, { -1,  0 }, {  0,  0 }, { -1,  1 } } },
711)   } },
712)   // the S
713)   { {
714)       { { {  0, -1 }, {  1, -1 }, { -1,  0 }, {  0,  0 } } },
715)       { { { -1, -1 }, { -1,  0 }, {  0,  0 }, {  0,  1 } } },
716)       { { {  0, -1 }, {  1, -1 }, { -1,  0 }, {  0,  0 } } },
717)       { { { -1, -1 }, { -1,  0 }, {  0,  0 }, {  0,  1 } } },
718)   } },
719) };
720) 
721) /// number of stones
722) int const Tetris::c_stoneCnt = sizeof(Tetris::c_stones) /
723)                                sizeof(Tetris::c_stones[0]);
724) /// number of rotations per stone
725) int const Tetris::c_rotCnt = sizeof(Tetris::Stone::rot) /
726)                              sizeof(Tetris::Stone::rot[0]);
727) /// number of pixels per stone
728) int const Tetris::c_pixelCnt = sizeof(Tetris::RotStone::pixels) /
729)                                sizeof(Tetris::RotStone::pixels[0]);
730) 
731) /// descriptor for delay value
Stefan Schuermans tetris WIP: move/freeze stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

733) 
Stefan Schuermans tetris: dropping stones

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

740) /// descriptor for delay value at end of game
741) Tetris::ValueDescr const Tetris::c_gameOverDelayDescr = { 2000, 100, 5000 };
742)