fb06c1c4fd5890e8d48b110fbcbe7b43adaf90c4
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) {
183)   // left player
184)   if (pConn == m_pConnLeft) {
185)     processKey(key, m_leftPosY);
186)   }
187)   // right player
Stefan Schuermans pong: activate when player...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

189)     processKey(key, m_rightPosY);
190)   }
191) }
192) 
193) /**
194)  * @brief play command received on operator connection
195)  * @param[in] pConn operator connection object
196)  * @param[in] sound name of sound to play
197)  */
198) void Pong::opConnRecvPlay(OpConn *pConn, const std::string &sound)
199) {
200)   (void)pConn;
201)   (void)sound;
202) }
203) 
204) /**
205)  * @brief operator connection is closed
206)  * @param[in] pConn operator connection object
207)  *
208)  * The connection may not be used for sending any more in this callback.
209)  */
210) void Pong::opConnClose(OpConn *pConn)
211) {
Stefan Schuermans add op conn close requests

Stefan Schuermans authored 5 years ago

212)   // remove coperator connection from requests (if it was in)
213)   forgetOpConn(pConn);
214) 
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

215)   // left player leaves
216)   if (pConn == m_pConnLeft) {
217)     m_pConnLeft = NULL;
218)   }
219)   // right player leaves
Stefan Schuermans pong: activate when player...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

222)   }
223)   // nothing happens
224)   else {
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

225)     return;
226)   }
Stefan Schuermans pong: activate when player...

Stefan Schuermans authored 5 years ago

227) 
228)   // still a phone player there
229)   if (m_pConnLeft || m_pConnRight) {
230)     redraw(); // player color is different for phone / computer
231)   }
232)   // no phone players left
233)   else {
234)     deactivate();
235)   }
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

236) }
237) 
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

241)   // compute parameters
242)   m_padSize = (m_height + 1) / 3;
243)   m_leftPosY = (m_height - m_padSize) / 2;
244)   m_rightPosY = (m_height - m_padSize) / 2;
Stefan Schuermans pong: make computer slow

Stefan Schuermans authored 5 years ago

245)   m_leftDelay = 0;
246)   m_rightDelay = 0;
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

247) 
248)   // convert colors
249)   color2data(m_fileBallColor, m_ballColor);
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

253)   color2data(m_fileScoreColor, m_scoreColor);
254)   color2data(m_fileGoalColor, m_goalColor);
Stefan Schuermans pong: configurable speed

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

259)   // reset scores
260)   m_scoreLeft = 0;
261)   m_scoreRight = 0;
262) 
263)   // start first ball
Stefan Schuermans pong: start ball at side

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

266) }
267) 
268) /// redraw current game image, expected to call sendFrame() at end
269) void Pong::redraw()
270) {
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

271)   int y, x;
272) 
273)   // draw background
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

276)   // draw middle line: single line on odd width, two dashed lines at even width
277)   for (y = 0; y < m_height; ++y) {
278)     x = (m_width - (y & 1)) / 2;
279)     pixel(y, x, m_lineColor);
280)   }
281) 
Stefan Schuermans pong: display score

Stefan Schuermans authored 5 years ago

282)   // draw score
283)   ColorData const &scoreColor = m_goalDelay <= 0 ? m_scoreColor : m_goalColor;
284)   y = (m_height - 1) / 2;
285)   x = m_width / 4;
286)   number3x5(y, x, 0, 0, m_scoreLeft, scoreColor);
287)   number3x5(y, m_width - 1 - x, 0, 0, m_scoreRight, scoreColor);
288) 
Stefan Schuermans pong: add pads

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

290)   lineVert(m_leftPosY, m_leftPosY + m_padSize - 1, 0,
291)            m_pConnLeft ? m_padColor : m_computerColor);
292)   lineVert(m_rightPosY, m_rightPosY + m_padSize - 1, m_width - 1,
293)            m_pConnRight ? m_padColor : m_computerColor);
Stefan Schuermans pong: add pads

Stefan Schuermans authored 5 years ago

294) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

299) 
300)   // send updated image buffer as frame
301)   sendFrame();
302) }
303) 
Stefan Schuermans move time call logic to gam...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

309) 
310)     // computer player: move pads
311)     if (! m_pConnLeft) {
312)       computerLeft();
313)     }
314)     if (! m_pConnRight) {
315)       computerRight();
316)     }
317) 
318)     // bounce ball
319)     bounceBall();
320) 
321)     // move ball
322)     m_ballPosX += m_ballDirX;
323)     m_ballPosY += m_ballDirY;
324) 
325)     // detect goal
326)     detectGoal();
327) 
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

331) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

336)         // maximum score reached
337)         if (m_scoreLeft >= (int)m_maxScore ||
338)             m_scoreRight >= (int)m_maxScore) {
339)           gameOver();
340)           return; // no gameOver() calls deactivate(), no need to redraw
341)         }
342)         // game continues with new ball
343)         else {
344)           startBall();
Stefan Schuermans move time call logic to gam...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

347)     }
348) 
349)   }
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

350) 
351)   // draw and send frame
352)   redraw();
353) 
Stefan Schuermans move time call logic to gam...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

356) }
357) 
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

358) /**
359)  * @brief process key received from phone player
360)  * @param[in] key received key from player
361)  * @param[in,out] padPosY y position of player's pad
362)  */
363) void Pong::processKey(char key, int &padPosY)
364) {
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

365)   // do not move pad if goal delay is active
366)   if (m_goalDelay > 0) {
367)     return;
368)   }
369) 
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

370)   // move pad (2 = up, 8 = down), do not move pad out of field
371)   if (key == '2' && padPosY > 0) {
372)     --padPosY;
373)     redraw();
374)   }
375)   else if (key == '8' && padPosY < m_height - m_padSize) {
376)     ++padPosY;
377)     redraw();
378)   }
379) }
380) 
Stefan Schuermans pong: make computer slow

Stefan Schuermans authored 5 years ago

381) /**
382)  * @brief delay processing for computer players
383)  * @param[in,out] delay delay variable of computer player
384)  * @return whether computer player is allowed to move
385)  */
386) bool Pong::computerDelay(int &delay) const
387) 
388) {
389)   // zero delay: generate new delay
390)   if (delay <= 0) {
391)     int avg_steps = (m_height - m_padSize) / 2;
392)     int delay_range = avg_steps > 1 ? m_width / avg_steps: m_width;
393)     delay = rand() % delay_range + delay_range;
394)   }
395) 
396)   // count down delay
397)   --delay;
398) 
399)   // moving allowd if delay expired
400)   return delay <= 0;
401) }
402) 
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

403) /**
404)  * @brief computation of ideal pad position for computer players
405)  * @param[in] padBallX x coordinate of position of ball when hitting the pad
406)  * @param[in] padY current y coordinate of pad
407)  * @param[out] padYmin minimum ideal y position of pad
408)  * @param[out] padYmax maximum ideal y position of pad
409)  */
410) void Pong::computerComputePadPos(int padBallX, int padY,
411)                                  int &padYmin, int &padYmax) const
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

412) {
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

413)   // ball not moving towards pad
414)   if ((padBallX - m_ballPosX) * m_ballDirX <= 0) {
415)     // do not move if ball is still close to pad
416)     if (abs(padBallX - m_ballPosX) <= 2) {
417)       padYmin = padY;
418)       padYmax = padY;
419)       return;
420)     }
421)     // move pad to middle (might be 2 pixels wide)
422)     padYmin = (m_height - m_padSize) / 2;
423)     padYmax = (m_height - m_padSize + 1) / 2;
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

424)     return;
425)   }
426) 
427)   // compute expected ball position at pad
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

428)   int ballPosX = m_ballPosX; // simulate were ball is going
429)   int ballPosY = m_ballPosY;
430)   int ballDirY = m_ballDirY;
431)   while ((padBallX - ballPosX) * m_ballDirX > 0) { // while moving to pad
432)     int deltaX = padBallX - ballPosX;
433)     int deltaY = deltaX * m_ballDirX * ballDirY;
434)     if (deltaY < -ballPosY) {
435)       deltaY = -ballPosY;
436)       ballPosX += deltaY * m_ballDirX * ballDirY;
437)       ballPosY = 0;
438)       ballDirY = 1;
439)     }
440)     else if (deltaY > m_height - 1 - ballPosY) {
441)       deltaY = m_height - 1 - ballPosY;
442)       ballPosX += deltaY * m_ballDirX * ballDirY;
443)       ballPosY = m_height - 1;
444)       ballDirY = -1;
445)     } else {
446)       ballPosX += deltaX;
447)       ballPosY += deltaY;
448)     }
449)   }
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

452)   padYmin = ballPosY - m_padSize / 2;
453)   padYmax = ballPosY - (m_padSize - 1) / 2;
454) }
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

455) 
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

456) /**
457)  * @brief move pad for computer players
458)  * @param[in] padYmin minimum desired y position of pad
459)  * @param[in] padYmax maximum desired y position of pad
460)  * @param[in,out] padPosY y position of pad
461)  */
462) void Pong::computerMovePad(int padYmin, int padYmax, int &padPosY) const
463) {
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

464)   // do not move pad if goal delay is active
465)   if (m_goalDelay > 0) {
466)     return;
467)   }
468) 
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

472)   }
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

475)   }
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

477) 
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

478) /// computer player for left pad
479) void Pong::computerLeft()
480) {
Stefan Schuermans pong: make computer slow

Stefan Schuermans authored 5 years ago

481)   if (computerDelay(m_leftDelay)) {
482)     int padYmin, padYmax;
483)     computerComputePadPos(1, m_leftPosY, padYmin, padYmax);
484)     computerMovePad(padYmin, padYmax, m_leftPosY);
485)   }
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

486) }
487) 
488) /// computer player for right pad
489) void Pong::computerRight()
490) {
Stefan Schuermans pong: make computer slow

Stefan Schuermans authored 5 years ago

491)   if (computerDelay(m_rightDelay)) {
492)     int padYmin, padYmax;
493)     computerComputePadPos(m_width - 2, m_rightPosY, padYmin, padYmax);
494)     computerMovePad(padYmin, padYmax, m_rightPosY);
495)   }
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

496) }
497) 
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

498) /// bounce ball
499) void Pong::bounceBall()
500) {
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

502)   bounceBallLeft();
503)   bounceBallRight();
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

505) }
506) 
507) /// bounce ball at sides
508) void Pong::bounceBallSide()
509) {
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

510)   if (m_ballPosY <= 0 && m_ballDirY < 0) {
511)     m_ballDirY = 1;
512)   }
513)   if (m_ballPosY >= m_height - 1 && m_ballDirY > 0) {
514)     m_ballDirY = -1;
515)   }
516)   if (m_ballPosX <= 0 && m_ballDirX < 0) {
517)     m_ballDirX = 1;
518)   }
519)   if (m_ballPosX >= m_width - 1 && m_ballDirX > 0) {
520)     m_ballDirX = -1;
521)   }
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

522) }
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

524) /// bounce ball at left pad
525) void Pong::bounceBallLeft()
526) {
527)   if (m_ballPosX != 1 || m_ballDirX >= 0) {
528)     return;
Stefan Schuermans pong: add pads

Stefan Schuermans authored 5 years ago

529)   }
530) 
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

531)   // top corner
532)   if (m_ballPosY == m_leftPosY - 1 && m_ballDirY > 0) {
533)     m_ballDirX = 1;
534)     m_ballDirY = -1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

536)   }
537) 
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

538)   // bottom corner
539)   else if (m_ballPosY == m_leftPosY + m_padSize && m_ballDirY < 0) {
540)     m_ballDirX = 1;
541)     m_ballDirY = 1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

543)   }
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

545)   // pad edge
546)   else if (m_ballPosY >= m_leftPosY &&
547)            m_ballPosY < m_leftPosY + m_padSize) {
548)     m_ballDirX = 1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

550)   }
551) }
552) 
553) /// bounce ball at right pad
554) void Pong::bounceBallRight()
555) {
556)   if (m_ballPosX != m_width - 2 || m_ballDirX <= 0) {
557)     return;
558)   }
559) 
560)   // top corner
561)   if (m_ballPosY == m_rightPosY - 1 && m_ballDirY > 0) {
562)     m_ballDirX = -1;
563)     m_ballDirY = -1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

565)   }
566) 
567)   // bottom corner
568)   else if (m_ballPosY == m_rightPosY + m_padSize && m_ballDirY < 0) {
569)     m_ballDirX = -1;
570)     m_ballDirY = 1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

572)   }
573) 
574)   // pad edge
575)   else if (m_ballPosY >= m_rightPosY &&
576)            m_ballPosY < m_rightPosY + m_padSize) {
577)     m_ballDirX = -1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

578)     ++m_bounceCnt;
579)   }
580) }
581) 
582) /// detect goal
583) void Pong::detectGoal()
584) {
585)   static int goalBlinkCnt = 3;
586)   static int goalDelay = goalBlinkCnt * 8 + 3;
587) 
588)   // ball at far left - goal for right player
589)   if (m_ballPosX == 0) {
590)     m_goalDelay = goalDelay;
591)     ++m_scoreRight;
Stefan Schuermans sound support for pong game

Stefan Schuermans authored 5 years ago

592)     // play sound - score or win
593)     if (m_scoreRight >= (int)m_maxScore) {
594)       playOpConnSound(m_pConnRight, m_fileWinSound);
595)       playOpConnSound(m_pConnLeft, m_fileLoseSound);
596)     } else {
597)       playOpConnSound(m_pConnRight, m_fileScoreSound);
598)       playOpConnSound(m_pConnLeft, m_fileOtherScoreSound);
599)     }
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

600)   }
601) 
602)   // ball at far right - goal for left player
603)   else if (m_ballPosX == m_width - 1) {
604)     m_goalDelay = goalDelay;
605)     ++m_scoreLeft;
Stefan Schuermans sound support for pong game

Stefan Schuermans authored 5 years ago

606)     // play sound - score or win
607)     if (m_scoreLeft >= (int)m_maxScore) {
608)       playOpConnSound(m_pConnLeft, m_fileWinSound);
609)       playOpConnSound(m_pConnRight, m_fileLoseSound);
610)     } else {
611)       playOpConnSound(m_pConnLeft, m_fileScoreSound);
612)       playOpConnSound(m_pConnRight, m_fileOtherScoreSound);
613)     }
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

614)   }
615) }
616) 
Stefan Schuermans move time call logic to gam...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

623)     return;
624)   }
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

625) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

630) 
631)   // request next time call
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

635) }
636) 
637) /// start ball
638) void Pong::startBall()
639) {
Stefan Schuermans pong: start ball at side

Stefan Schuermans authored 5 years ago

640)   // horizontal start direction opposite as before goal or random
641)   if (m_ballDirX > 0) {
642)     m_ballDirX = -1;
643)   } else if (m_ballDirX < 0) {
644)     m_ballDirX = 1;
645)   } else {
646)     m_ballDirX = (rand() & 1) * 2 - 1;
647)   }
648)   // random vertical start direction
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

651)   // horizontal start postion at side of field (depending on direction)
652)   m_ballPosX = m_ballDirX > 0 ? 0 : m_width - 1;
653)   // random vertical start position
654)   m_ballPosY = rand() % m_height;
655) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

656)   // no delays, ball has not bounced at pad
657)   m_leftDelay = 0;
658)   m_rightDelay = 0;
659)   m_goalDelay = 0;
660)   m_bounceCnt = 0;
661) 
662)   // draw and send frame
663)   redraw();
664) 
Stefan Schuermans move time call logic to gam...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

667) }
668) 
Stefan Schuermans pong: end game when max sco...

Stefan Schuermans authored 5 years ago

669) /// game over: close player connections and deactivate
670) void Pong::gameOver()
671) {
672)   // close open operator connections
673)   if (m_pConnLeft) {
Stefan Schuermans add op conn close requests

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

675)     m_pConnLeft->close();
676)     m_pConnLeft = NULL;
677)   }
678)   if (m_pConnRight) {
Stefan Schuermans add op conn close requests

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

680)     m_pConnRight->close();
681)     m_pConnRight = NULL;
682)   }
683) 
684)   // deactivate game
685)   deactivate();
686) }
687)