7dc2eb4a2d6a4ae0fde4acc5360bd005d1cabe60
Stefan Schuermans begin of Pong game

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) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

6) #include <cmath>
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

7) #include <stdlib.h>
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

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"
Stefan Schuermans sound support for pong game

Stefan Schuermans authored 5 years ago

19) #include "NameFile.h"
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

20) #include "OpConn.h"
21) #include "OpConnIf.h"
22) #include "OpReqIf.h"
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

23) #include "OutStreamFile.h"
24) #include "Pong.h"
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

25) #include "Time.h"
26) #include "TimeCallee.h"
Stefan Schuermans pong: configurable speed

Stefan Schuermans authored 5 years ago

27) #include "UIntFile.h"
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

28) 
29) namespace Blinker {
30) 
Stefan Schuermans pong: configurable speed

Stefan Schuermans authored 5 years ago

31) /// descriptor for delay value
32) Pong::ValueDescr const Pong::c_delayDescr = { 200, 100, 500 };
Stefan Schuermans pong: end game when max sco...

Stefan Schuermans authored 5 years ago

33) /// descriptor for maximum score value
34) Pong::ValueDescr const Pong::c_maxScoreDescr = { 9, 1, 99 };
Stefan Schuermans pong: configurable speed

Stefan Schuermans authored 5 years ago

35) 
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

36) /// operator connection name suffix for left player's connection
Stefan Schuermans pong: configurable speed

Stefan Schuermans authored 5 years ago

37) std::string const Pong::c_opConnSuffixLeft = "/left";
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

38) /// operator connection name suffix for right player's connection
Stefan Schuermans pong: configurable speed

Stefan Schuermans authored 5 years ago

39) std::string const Pong::c_opConnSuffixRight = "/right";
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

40) 
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

41) /**
42)  * @brief constructor
43)  * @param[in] name module name
44)  * @param[in] mgrs managers
45)  * @param[in] dirBase base directory
46)  */
47) Pong::Pong(const std::string &name, Mgrs &mgrs, const Directory &dirBase):
48)   Game(name, mgrs, dirBase),
49)   m_fileBallColor(dirBase.getFile("ballColor")),
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

50)   m_fileLineColor(dirBase.getFile("lineColor")),
Stefan Schuermans pong: add pads

Stefan Schuermans authored 5 years ago

51)   m_filePadColor(dirBase.getFile("padColor")),
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

52)   m_fileComputerColor(dirBase.getFile("computerColor")),
Stefan Schuermans pong: display score

Stefan Schuermans authored 5 years ago

53)   m_fileScoreColor(dirBase.getFile("scoreColor")),
54)   m_fileGoalColor(dirBase.getFile("goalColor")),
Stefan Schuermans pong: configurable speed

Stefan Schuermans authored 5 years ago

55)   m_fileDelay(dirBase.getFile("delay")),
Stefan Schuermans pong: end game when max sco...

Stefan Schuermans authored 5 years ago

56)   m_fileMaxScore(dirBase.getFile("maxScore")),
Stefan Schuermans sound support for pong game

Stefan Schuermans authored 5 years ago

57)   m_fileLeftPlayerSound(dirBase.getFile("leftPlayerSound")),
58)   m_fileRightPlayerSound(dirBase.getFile("rightPlayerSound")),
59)   m_fileScoreSound(dirBase.getFile("scoreSound")),
60)   m_fileOtherScoreSound(dirBase.getFile("otherScoreSound")),
61)   m_fileWinSound(dirBase.getFile("winSound")),
62)   m_fileLoseSound(dirBase.getFile("loseSound")),
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

63)   m_ballColor(), m_lineColor(), m_padColor(), m_computerColor(),
Stefan Schuermans pong: display score

Stefan Schuermans authored 5 years ago

64)   m_scoreColor(), m_goalColor(),
Stefan Schuermans pong: end game when max sco...

Stefan Schuermans authored 5 years ago

65)   m_delay(c_delayDescr.default_), m_maxScore(c_maxScoreDescr.default_),
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

66)   m_pConnLeft(NULL), m_pConnRight(NULL),
Stefan Schuermans pong: add pads

Stefan Schuermans authored 5 years ago

67)   m_ballPosX(-1), m_ballPosY(-1), m_ballDirX(0), m_ballDirY(0),
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

68)   m_padSize(0), m_leftPosY(0), m_rightPosY(0), m_leftDelay(0), m_rightDelay(0),
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

69)   m_goalDelay(0), m_bounceCnt(0), m_scoreLeft(0), m_scoreRight(0)
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

70) {
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

71)   // open operator connection interfaces for left and right player
Stefan Schuermans pong: configurable speed

Stefan Schuermans authored 5 years ago

72)   m_mgrs.m_opMgr.open(m_name + c_opConnSuffixLeft, this);
73)   m_mgrs.m_opMgr.open(m_name + c_opConnSuffixRight, this);
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

74) }
75) 
76) /// virtual destructor
77) Pong::~Pong()
78) {
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

79)   // close operator connection interfaces
Stefan Schuermans pong: configurable speed

Stefan Schuermans authored 5 years ago

80)   m_mgrs.m_opMgr.close(m_name + c_opConnSuffixLeft);
81)   m_mgrs.m_opMgr.close(m_name + c_opConnSuffixRight);
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

82) 
83)   // close open operator connections
84)   if (m_pConnLeft) {
85)     m_pConnLeft->close();
86)     m_pConnLeft = NULL;
87)   }
88)   if (m_pConnRight) {
89)     m_pConnRight->close();
90)     m_pConnRight = NULL;
91)   }
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

92) }
93) 
94) /// check for update of configuration (derived game), return true on update
95) bool Pong::updateConfigGame()
96) {
97)   bool ret = false;
98) 
99)   // color file was modified -> convert color, return true for update
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

100)   if (colorUpdate(m_fileBallColor, m_ballColor) ||
Stefan Schuermans pong: add pads

Stefan Schuermans authored 5 years ago

101)       colorUpdate(m_fileLineColor, m_lineColor) ||
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

102)       colorUpdate(m_filePadColor, m_padColor) ||
Stefan Schuermans pong: display score

Stefan Schuermans authored 5 years ago

103)       colorUpdate(m_fileComputerColor, m_computerColor) ||
104)       colorUpdate(m_fileScoreColor, m_scoreColor) ||
Stefan Schuermans pong: configurable speed

Stefan Schuermans authored 5 years ago

105)       colorUpdate(m_fileGoalColor, m_goalColor) ||
Stefan Schuermans pong: end game when max sco...

Stefan Schuermans authored 5 years ago

106)       valueUpdate(m_fileDelay, c_delayDescr, m_delay) ||
107)       valueUpdate(m_fileMaxScore, c_maxScoreDescr, m_maxScore)) {
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

108)     ret = true;
109)   }
110) 
Stefan Schuermans sound support for pong game

Stefan Schuermans authored 5 years ago

111)   // sound name file was modified -> re-read sound name, no other update needed
112)   soundUpdate(m_fileLeftPlayerSound);
113)   soundUpdate(m_fileRightPlayerSound);
114)   soundUpdate(m_fileScoreSound);
115)   soundUpdate(m_fileOtherScoreSound);
116)   soundUpdate(m_fileWinSound);
117)   soundUpdate(m_fileLoseSound);
118) 
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

119)   return ret;
120) }
121) 
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

122) /**
Stefan Schuermans fix comment typo

Stefan Schuermans authored 5 years ago

123)  * @brief check if accepting new operator connection is possible
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

124)  * @param[in] name operator interface name
125)  * @return if accepting new connection is possible
126)  */
127) bool Pong::acceptNewOpConn(const std::string &name)
128) {
129)   // left player can join if none there yet
Stefan Schuermans pong: configurable speed

Stefan Schuermans authored 5 years ago

130)   if (name == m_name + c_opConnSuffixLeft && ! m_pConnLeft) {
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

131)     return true;
132)   }
133)   // right player can join if none there yet
Stefan Schuermans pong: configurable speed

Stefan Schuermans authored 5 years ago

134)   if (name == m_name + c_opConnSuffixRight && ! m_pConnRight) {
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

135)     return true;
136)   }
137)   // default: reject connection
138)   return false;
139) }
140) 
141) /**
142)  * @brief new operator connection
143)  * @param[in] name operator interface name
144)  * @param[in] pConn operator connection object
145)  *
146)  * The new connection may not yet be used for sending inside this callback.
147)  */
148) void Pong::newOpConn(const std::string &name, OpConn *pConn)
149) {
150)   // left player joins if none there yet
Stefan Schuermans pong: configurable speed

Stefan Schuermans authored 5 years ago

151)   if (name == m_name + c_opConnSuffixLeft && ! m_pConnLeft) {
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

152)     m_pConnLeft = pConn;
Stefan Schuermans sound support for pong game

Stefan Schuermans authored 5 years ago

153)     requestOpConnSound(m_pConnLeft, m_fileLeftPlayerSound);
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

154)   }
155)   // right player joins if none there yet
Stefan Schuermans pong: configurable speed

Stefan Schuermans authored 5 years ago

156)   else if (name == m_name + c_opConnSuffixRight && ! m_pConnRight) {
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

157)     m_pConnRight = pConn;
Stefan Schuermans sound support for pong game

Stefan Schuermans authored 5 years ago

158)     requestOpConnSound(m_pConnRight, m_fileRightPlayerSound);
Stefan Schuermans pong: activate when player...

Stefan Schuermans authored 5 years ago

159)   }
Stefan Schuermans add op conn close requests

Stefan Schuermans authored 5 years ago

160)   // close imcoming connection as soon as possible, nothing else happens
Stefan Schuermans pong: activate when player...

Stefan Schuermans authored 5 years ago

161)   else {
Stefan Schuermans add op conn close requests

Stefan Schuermans authored 5 years ago

162)     requestOpConnClose(pConn);
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

163)     return;
164)   }
Stefan Schuermans pong: activate when player...

Stefan Schuermans authored 5 years ago

165) 
166)   // already active
167)   if (isActive()) {
168)     redraw(); // player color is different for phone / computer
169)   }
170)   // first player joined
171)   else {
172)     activate();
173)   }
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

174) }
175) 
176) /**
177)  * @brief key command received on operator connection
178)  * @param[in] pConn operator connection object
179)  * @param[in] key key that was pressed
180)  */
181) void Pong::opConnRecvKey(OpConn *pConn, char key)
182) {
Stefan Schuermans pong: hash -> hangup, star...

Stefan Schuermans authored 5 years ago

183)   // hash -> hang up
184)   if (key == '#') {
185)     opConnClose(pConn);
186)     pConn->close();
187)     return;
188)   }
189) 
190)   // star -> inform player about it side
191)   if (key == '*') {
192)     if (pConn == m_pConnLeft) {
193)       playOpConnSound(pConn, m_fileLeftPlayerSound);
194)     } else if (pConn == m_pConnRight) {
195)       playOpConnSound(pConn, m_fileRightPlayerSound);
196)     }
197)     return;
198)   }
199) 
200)   // normal keys for controlling game
201) 
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

202)   // left player
203)   if (pConn == m_pConnLeft) {
204)     processKey(key, m_leftPosY);
205)   }
206)   // right player
Stefan Schuermans pong: activate when player...

Stefan Schuermans authored 5 years ago

207)   else if (pConn == m_pConnRight) {
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

208)     processKey(key, m_rightPosY);
209)   }
210) }
211) 
212) /**
213)  * @brief play command received on operator connection
214)  * @param[in] pConn operator connection object
215)  * @param[in] sound name of sound to play
216)  */
217) void Pong::opConnRecvPlay(OpConn *pConn, const std::string &sound)
218) {
219)   (void)pConn;
220)   (void)sound;
221) }
222) 
223) /**
224)  * @brief operator connection is closed
225)  * @param[in] pConn operator connection object
226)  *
227)  * The connection may not be used for sending any more in this callback.
228)  */
229) void Pong::opConnClose(OpConn *pConn)
230) {
Stefan Schuermans add op conn close requests

Stefan Schuermans authored 5 years ago

231)   // remove coperator connection from requests (if it was in)
232)   forgetOpConn(pConn);
233) 
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

234)   // left player leaves
235)   if (pConn == m_pConnLeft) {
236)     m_pConnLeft = NULL;
237)   }
238)   // right player leaves
Stefan Schuermans pong: activate when player...

Stefan Schuermans authored 5 years ago

239)   else if (pConn == m_pConnRight) {
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

240)     m_pConnRight = NULL;
Stefan Schuermans pong: activate when player...

Stefan Schuermans authored 5 years ago

241)   }
242)   // nothing happens
243)   else {
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

244)     return;
245)   }
Stefan Schuermans pong: activate when player...

Stefan Schuermans authored 5 years ago

246) 
247)   // still a phone player there
248)   if (m_pConnLeft || m_pConnRight) {
249)     redraw(); // player color is different for phone / computer
250)   }
251)   // no phone players left
252)   else {
253)     deactivate();
254)   }
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

255) }
256) 
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

257) /// re-initialize game (e.g. due to config change)
258) void Pong::reinitialize()
259) {
Stefan Schuermans pong: add pads

Stefan Schuermans authored 5 years ago

260)   // compute parameters
261)   m_padSize = (m_height + 1) / 3;
262)   m_leftPosY = (m_height - m_padSize) / 2;
263)   m_rightPosY = (m_height - m_padSize) / 2;
Stefan Schuermans pong: make computer slow

Stefan Schuermans authored 5 years ago

264)   m_leftDelay = 0;
265)   m_rightDelay = 0;
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

266) 
267)   // convert colors
268)   color2data(m_fileBallColor, m_ballColor);
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

269)   color2data(m_fileLineColor, m_lineColor);
Stefan Schuermans pong: add pads

Stefan Schuermans authored 5 years ago

270)   color2data(m_filePadColor, m_padColor);
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

271)   color2data(m_fileComputerColor, m_computerColor);
Stefan Schuermans pong: display score

Stefan Schuermans authored 5 years ago

272)   color2data(m_fileScoreColor, m_scoreColor);
273)   color2data(m_fileGoalColor, m_goalColor);
Stefan Schuermans pong: configurable speed

Stefan Schuermans authored 5 years ago

274)   // get values
275)   valueFromFile(m_fileDelay, c_delayDescr, m_delay);
Stefan Schuermans pong: end game when max sco...

Stefan Schuermans authored 5 years ago

276)   valueFromFile(m_fileMaxScore, c_maxScoreDescr, m_maxScore);
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

277) 
Stefan Schuermans pong: activate when player...

Stefan Schuermans authored 5 years ago

278)   // reset scores
279)   m_scoreLeft = 0;
280)   m_scoreRight = 0;
281) 
282)   // start first ball
Stefan Schuermans pong: start ball at side

Stefan Schuermans authored 5 years ago

283)   m_ballDirX = 0; // start at random side
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

284)   startBall();
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

285) }
286) 
287) /// redraw current game image, expected to call sendFrame() at end
288) void Pong::redraw()
289) {
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

290)   int y, x;
291) 
292)   // draw background
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

293)   rectFill(0, m_height, 0, m_width, m_backgroundColor);
294) 
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

295)   // draw middle line: single line on odd width, two dashed lines at even width
296)   for (y = 0; y < m_height; ++y) {
297)     x = (m_width - (y & 1)) / 2;
298)     pixel(y, x, m_lineColor);
299)   }
300) 
Stefan Schuermans pong: display score

Stefan Schuermans authored 5 years ago

301)   // draw score
302)   ColorData const &scoreColor = m_goalDelay <= 0 ? m_scoreColor : m_goalColor;
303)   y = (m_height - 1) / 2;
304)   x = m_width / 4;
305)   number3x5(y, x, 0, 0, m_scoreLeft, scoreColor);
306)   number3x5(y, m_width - 1 - x, 0, 0, m_scoreRight, scoreColor);
307) 
Stefan Schuermans pong: add pads

Stefan Schuermans authored 5 years ago

308)   // draw pads
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

309)   lineVert(m_leftPosY, m_leftPosY + m_padSize - 1, 0,
310)            m_pConnLeft ? m_padColor : m_computerColor);
311)   lineVert(m_rightPosY, m_rightPosY + m_padSize - 1, m_width - 1,
312)            m_pConnRight ? m_padColor : m_computerColor);
Stefan Schuermans pong: add pads

Stefan Schuermans authored 5 years ago

313) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

314)   // draw ball (blinking if goal delay is active)
315)   if (m_goalDelay <= 0 || (m_goalDelay & 4) == 0) {
316)       pixel(m_ballPosY, m_ballPosX, m_ballColor);
317)   }
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

318) 
319)   // send updated image buffer as frame
320)   sendFrame();
321) }
322) 
Stefan Schuermans move time call logic to gam...

Stefan Schuermans authored 5 years ago

323) /// process next time step of game
324) void Pong::timeStep()
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

325) {
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

326)   // game is running
Stefan Schuermans pong: activate when player...

Stefan Schuermans authored 5 years ago

327)   if (m_goalDelay <= 0) {
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

328) 
329)     // computer player: move pads
330)     if (! m_pConnLeft) {
331)       computerLeft();
332)     }
333)     if (! m_pConnRight) {
334)       computerRight();
335)     }
336) 
337)     // bounce ball
338)     bounceBall();
339) 
340)     // move ball
341)     m_ballPosX += m_ballDirX;
342)     m_ballPosY += m_ballDirY;
343) 
344)     // detect goal
345)     detectGoal();
346) 
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

347)   }
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

348)   // goal delay (blinking ball)
349)   else if (m_goalDelay > 0) {
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

350) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

351)     --m_goalDelay;
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

352) 
Stefan Schuermans pong: end game when max sco...

Stefan Schuermans authored 5 years ago

353)     // delay is over
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

354)     if (m_goalDelay <= 0) {
Stefan Schuermans pong: end game when max sco...

Stefan Schuermans authored 5 years ago

355)         // maximum score reached
356)         if (m_scoreLeft >= (int)m_maxScore ||
357)             m_scoreRight >= (int)m_maxScore) {
358)           gameOver();
359)           return; // no gameOver() calls deactivate(), no need to redraw
360)         }
361)         // game continues with new ball
362)         else {
363)           startBall();
Stefan Schuermans move time call logic to gam...

Stefan Schuermans authored 5 years ago

364)           return; // startBall() calls redraw() and planTimeStep()
Stefan Schuermans pong: end game when max sco...

Stefan Schuermans authored 5 years ago

365)         }
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

366)     }
367) 
368)   }
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

369) 
370)   // draw and send frame
371)   redraw();
372) 
Stefan Schuermans move time call logic to gam...

Stefan Schuermans authored 5 years ago

373)   // request next time step
374)   planTimeStep();
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

375) }
376) 
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

377) /**
378)  * @brief process key received from phone player
379)  * @param[in] key received key from player
380)  * @param[in,out] padPosY y position of player's pad
381)  */
382) void Pong::processKey(char key, int &padPosY)
383) {
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

384)   // do not move pad if goal delay is active
385)   if (m_goalDelay > 0) {
386)     return;
387)   }
388) 
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

389)   // move pad (2 = up, 8 = down), do not move pad out of field
390)   if (key == '2' && padPosY > 0) {
391)     --padPosY;
392)     redraw();
393)   }
394)   else if (key == '8' && padPosY < m_height - m_padSize) {
395)     ++padPosY;
396)     redraw();
397)   }
398) }
399) 
Stefan Schuermans pong: make computer slow

Stefan Schuermans authored 5 years ago

400) /**
401)  * @brief delay processing for computer players
402)  * @param[in,out] delay delay variable of computer player
403)  * @return whether computer player is allowed to move
404)  */
405) bool Pong::computerDelay(int &delay) const
406) 
407) {
408)   // zero delay: generate new delay
409)   if (delay <= 0) {
410)     int avg_steps = (m_height - m_padSize) / 2;
411)     int delay_range = avg_steps > 1 ? m_width / avg_steps: m_width;
412)     delay = rand() % delay_range + delay_range;
413)   }
414) 
415)   // count down delay
416)   --delay;
417) 
418)   // moving allowd if delay expired
419)   return delay <= 0;
420) }
421) 
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

422) /**
423)  * @brief computation of ideal pad position for computer players
424)  * @param[in] padBallX x coordinate of position of ball when hitting the pad
425)  * @param[in] padY current y coordinate of pad
426)  * @param[out] padYmin minimum ideal y position of pad
427)  * @param[out] padYmax maximum ideal y position of pad
428)  */
429) void Pong::computerComputePadPos(int padBallX, int padY,
430)                                  int &padYmin, int &padYmax) const
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

431) {
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

432)   // ball not moving towards pad
433)   if ((padBallX - m_ballPosX) * m_ballDirX <= 0) {
434)     // do not move if ball is still close to pad
435)     if (abs(padBallX - m_ballPosX) <= 2) {
436)       padYmin = padY;
437)       padYmax = padY;
438)       return;
439)     }
440)     // move pad to middle (might be 2 pixels wide)
441)     padYmin = (m_height - m_padSize) / 2;
442)     padYmax = (m_height - m_padSize + 1) / 2;
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

443)     return;
444)   }
445) 
446)   // compute expected ball position at pad
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

447)   int ballPosX = m_ballPosX; // simulate were ball is going
448)   int ballPosY = m_ballPosY;
449)   int ballDirY = m_ballDirY;
450)   while ((padBallX - ballPosX) * m_ballDirX > 0) { // while moving to pad
451)     int deltaX = padBallX - ballPosX;
452)     int deltaY = deltaX * m_ballDirX * ballDirY;
453)     if (deltaY < -ballPosY) {
454)       deltaY = -ballPosY;
455)       ballPosX += deltaY * m_ballDirX * ballDirY;
456)       ballPosY = 0;
457)       ballDirY = 1;
458)     }
459)     else if (deltaY > m_height - 1 - ballPosY) {
460)       deltaY = m_height - 1 - ballPosY;
461)       ballPosX += deltaY * m_ballDirX * ballDirY;
462)       ballPosY = m_height - 1;
463)       ballDirY = -1;
464)     } else {
465)       ballPosX += deltaX;
466)       ballPosY += deltaY;
467)     }
468)   }
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

469) 
470)   // compute pad position to hit ball with center of pad
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

471)   padYmin = ballPosY - m_padSize / 2;
472)   padYmax = ballPosY - (m_padSize - 1) / 2;
473) }
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

474) 
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

475) /**
476)  * @brief move pad for computer players
477)  * @param[in] padYmin minimum desired y position of pad
478)  * @param[in] padYmax maximum desired y position of pad
479)  * @param[in,out] padPosY y position of pad
480)  */
481) void Pong::computerMovePad(int padYmin, int padYmax, int &padPosY) const
482) {
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

483)   // do not move pad if goal delay is active
484)   if (m_goalDelay > 0) {
485)     return;
486)   }
487) 
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

488)   // move pad, do not move pad out of field
489)   if (padPosY > padYmax && padPosY > 0) {
490)     --padPosY;
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

491)   }
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

492)   else if (padPosY < padYmin && padPosY < m_height - m_padSize) {
493)     ++padPosY;
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

494)   }
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

495) }
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

496) 
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

497) /// computer player for left pad
498) void Pong::computerLeft()
499) {
Stefan Schuermans pong: make computer slow

Stefan Schuermans authored 5 years ago

500)   if (computerDelay(m_leftDelay)) {
501)     int padYmin, padYmax;
502)     computerComputePadPos(1, m_leftPosY, padYmin, padYmax);
503)     computerMovePad(padYmin, padYmax, m_leftPosY);
504)   }
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

505) }
506) 
507) /// computer player for right pad
508) void Pong::computerRight()
509) {
Stefan Schuermans pong: make computer slow

Stefan Schuermans authored 5 years ago

510)   if (computerDelay(m_rightDelay)) {
511)     int padYmin, padYmax;
512)     computerComputePadPos(m_width - 2, m_rightPosY, padYmin, padYmax);
513)     computerMovePad(padYmin, padYmax, m_rightPosY);
514)   }
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

515) }
516) 
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

517) /// bounce ball
518) void Pong::bounceBall()
519) {
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

520)   bounceBallSide(); // must be done before player bounce to be safe
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

521)   bounceBallLeft();
522)   bounceBallRight();
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

523)   bounceBallSide(); // must also be done after player bounce to be safe
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

524) }
525) 
526) /// bounce ball at sides
527) void Pong::bounceBallSide()
528) {
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

529)   if (m_ballPosY <= 0 && m_ballDirY < 0) {
530)     m_ballDirY = 1;
531)   }
532)   if (m_ballPosY >= m_height - 1 && m_ballDirY > 0) {
533)     m_ballDirY = -1;
534)   }
535)   if (m_ballPosX <= 0 && m_ballDirX < 0) {
536)     m_ballDirX = 1;
537)   }
538)   if (m_ballPosX >= m_width - 1 && m_ballDirX > 0) {
539)     m_ballDirX = -1;
540)   }
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

541) }
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

542) 
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

543) /// bounce ball at left pad
544) void Pong::bounceBallLeft()
545) {
546)   if (m_ballPosX != 1 || m_ballDirX >= 0) {
547)     return;
Stefan Schuermans pong: add pads

Stefan Schuermans authored 5 years ago

548)   }
549) 
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

550)   // top corner
551)   if (m_ballPosY == m_leftPosY - 1 && m_ballDirY > 0) {
552)     m_ballDirX = 1;
553)     m_ballDirY = -1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

554)     ++m_bounceCnt;
Stefan Schuermans pong: add pads

Stefan Schuermans authored 5 years ago

555)   }
556) 
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

557)   // bottom corner
558)   else if (m_ballPosY == m_leftPosY + m_padSize && m_ballDirY < 0) {
559)     m_ballDirX = 1;
560)     m_ballDirY = 1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

561)     ++m_bounceCnt;
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

562)   }
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

563) 
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

564)   // pad edge
565)   else if (m_ballPosY >= m_leftPosY &&
566)            m_ballPosY < m_leftPosY + m_padSize) {
567)     m_ballDirX = 1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

568)     ++m_bounceCnt;
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

569)   }
570) }
571) 
572) /// bounce ball at right pad
573) void Pong::bounceBallRight()
574) {
575)   if (m_ballPosX != m_width - 2 || m_ballDirX <= 0) {
576)     return;
577)   }
578) 
579)   // top corner
580)   if (m_ballPosY == m_rightPosY - 1 && m_ballDirY > 0) {
581)     m_ballDirX = -1;
582)     m_ballDirY = -1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

583)     ++m_bounceCnt;
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

584)   }
585) 
586)   // bottom corner
587)   else if (m_ballPosY == m_rightPosY + m_padSize && m_ballDirY < 0) {
588)     m_ballDirX = -1;
589)     m_ballDirY = 1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

590)     ++m_bounceCnt;
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

591)   }
592) 
593)   // pad edge
594)   else if (m_ballPosY >= m_rightPosY &&
595)            m_ballPosY < m_rightPosY + m_padSize) {
596)     m_ballDirX = -1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

597)     ++m_bounceCnt;
598)   }
599) }
600) 
601) /// detect goal
602) void Pong::detectGoal()
603) {
604)   static int goalBlinkCnt = 3;
605)   static int goalDelay = goalBlinkCnt * 8 + 3;
606) 
607)   // ball at far left - goal for right player
608)   if (m_ballPosX == 0) {
609)     m_goalDelay = goalDelay;
610)     ++m_scoreRight;
Stefan Schuermans sound support for pong game

Stefan Schuermans authored 5 years ago

611)     // play sound - score or win
612)     if (m_scoreRight >= (int)m_maxScore) {
613)       playOpConnSound(m_pConnRight, m_fileWinSound);
614)       playOpConnSound(m_pConnLeft, m_fileLoseSound);
615)     } else {
616)       playOpConnSound(m_pConnRight, m_fileScoreSound);
617)       playOpConnSound(m_pConnLeft, m_fileOtherScoreSound);
618)     }
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

619)   }
620) 
621)   // ball at far right - goal for left player
622)   else if (m_ballPosX == m_width - 1) {
623)     m_goalDelay = goalDelay;
624)     ++m_scoreLeft;
Stefan Schuermans sound support for pong game

Stefan Schuermans authored 5 years ago

625)     // play sound - score or win
626)     if (m_scoreLeft >= (int)m_maxScore) {
627)       playOpConnSound(m_pConnLeft, m_fileWinSound);
628)       playOpConnSound(m_pConnRight, m_fileLoseSound);
629)     } else {
630)       playOpConnSound(m_pConnLeft, m_fileScoreSound);
631)       playOpConnSound(m_pConnRight, m_fileOtherScoreSound);
632)     }
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

633)   }
634) }
635) 
Stefan Schuermans move time call logic to gam...

Stefan Schuermans authored 5 years ago

636) /// set time for next time step of game - or unset if not needed
637) void Pong::planTimeStep()
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

638) {
Stefan Schuermans pong: activate when player...

Stefan Schuermans authored 5 years ago

639)   // no time call needed if not active
640)   if (! isActive()) {
Stefan Schuermans move time call logic to gam...

Stefan Schuermans authored 5 years ago

641)     unsetTimeStep();
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

642)     return;
643)   }
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

644) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

645)   // compute interval based on score and bounce count
Stefan Schuermans pong: configurable speed

Stefan Schuermans authored 5 years ago

646)   int speedup = 10 * (m_scoreLeft + m_scoreRight) + m_bounceCnt;
647)   float scale = 0.3f + 0.7f * expf(-0.03f * speedup);
648)   float interval = 1e-3f * m_delay * scale;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

649) 
650)   // request next time call
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

651)   Time stepTime;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

652)   stepTime.fromFloatSec(interval);
Stefan Schuermans move time call logic to gam...

Stefan Schuermans authored 5 years ago

653)   setTimeStep(Time::now() + stepTime);
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

654) }
655) 
656) /// start ball
657) void Pong::startBall()
658) {
Stefan Schuermans pong: start ball at side

Stefan Schuermans authored 5 years ago

659)   // horizontal start direction opposite as before goal or random
660)   if (m_ballDirX > 0) {
661)     m_ballDirX = -1;
662)   } else if (m_ballDirX < 0) {
663)     m_ballDirX = 1;
664)   } else {
665)     m_ballDirX = (rand() & 1) * 2 - 1;
666)   }
667)   // random vertical start direction
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

668)   m_ballDirY = (rand() & 1) * 2 - 1;
669) 
Stefan Schuermans pong: start ball at side

Stefan Schuermans authored 5 years ago

670)   // horizontal start postion at side of field (depending on direction)
671)   m_ballPosX = m_ballDirX > 0 ? 0 : m_width - 1;
672)   // random vertical start position
673)   m_ballPosY = rand() % m_height;
674) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

675)   // no delays, ball has not bounced at pad
676)   m_leftDelay = 0;
677)   m_rightDelay = 0;
678)   m_goalDelay = 0;
679)   m_bounceCnt = 0;
680) 
681)   // draw and send frame
682)   redraw();
683) 
Stefan Schuermans move time call logic to gam...

Stefan Schuermans authored 5 years ago

684)   // request first time step if needed
685)   planTimeStep();
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

686) }
687) 
Stefan Schuermans pong: end game when max sco...

Stefan Schuermans authored 5 years ago

688) /// game over: close player connections and deactivate
689) void Pong::gameOver()
690) {
691)   // close open operator connections
692)   if (m_pConnLeft) {
Stefan Schuermans add op conn close requests

Stefan Schuermans authored 5 years ago

693)     forgetOpConn(m_pConnLeft); // remove from requests (if it was in)
Stefan Schuermans pong: end game when max sco...

Stefan Schuermans authored 5 years ago

694)     m_pConnLeft->close();
695)     m_pConnLeft = NULL;
696)   }
697)   if (m_pConnRight) {
Stefan Schuermans add op conn close requests

Stefan Schuermans authored 5 years ago

698)     forgetOpConn(m_pConnRight); // remove from requests (if it was in)
Stefan Schuermans pong: end game when max sco...

Stefan Schuermans authored 5 years ago

699)     m_pConnRight->close();
700)     m_pConnRight = NULL;
701)   }
702) 
703)   // deactivate game
704)   deactivate();
705) }
706)