ab0d0a082cc59ae70ee13a257a1a9ae0ea0bff2c
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) 
31) /**
32)  * @brief constructor
33)  * @param[in] name module name
34)  * @param[in] mgrs managers
35)  * @param[in] dirBase base directory
36)  */
37) Pong::Pong(const std::string &name, Mgrs &mgrs, const Directory &dirBase):
38)   Game(name, mgrs, dirBase),
39)   m_fileBallColor(dirBase.getFile("ballColor")),
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

47)   m_fileLeftPlayerSound(dirBase.getFile("leftPlayerSound")),
48)   m_fileRightPlayerSound(dirBase.getFile("rightPlayerSound")),
49)   m_fileScoreSound(dirBase.getFile("scoreSound")),
50)   m_fileOtherScoreSound(dirBase.getFile("otherScoreSound")),
51)   m_fileWinSound(dirBase.getFile("winSound")),
52)   m_fileLoseSound(dirBase.getFile("loseSound")),
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

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

Stefan Schuermans authored 5 years ago

60) {
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

64) }
65) 
66) /// virtual destructor
67) Pong::~Pong()
68) {
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

72) 
73)   // close open operator connections
74)   if (m_pConnLeft) {
75)     m_pConnLeft->close();
76)     m_pConnLeft = NULL;
77)   }
78)   if (m_pConnRight) {
79)     m_pConnRight->close();
80)     m_pConnRight = NULL;
81)   }
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

82) }
83) 
Stefan Schuermans change of some game params...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

91)   (void)doReinit;
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

93)   // color file was modified -> convert color, ask for redraw
94)   if (colorUpdate(m_fileBallColor, m_ballColor)) { doRedraw = true; }
95)   if (colorUpdate(m_fileLineColor, m_lineColor)) { doRedraw = true; }
96)   if (colorUpdate(m_filePadColor, m_padColor)) { doRedraw = true; }
97)   if (colorUpdate(m_fileComputerColor, m_computerColor)) { doRedraw = true; }
98)   if (colorUpdate(m_fileScoreColor, m_scoreColor)) { doRedraw = true; }
99)   if (colorUpdate(m_fileGoalColor, m_goalColor)) { doRedraw = true; }
100) 
101)   // cfg value file was updated -> read new cfg value, no reinit/redraw
102)   valueUpdate(m_fileDelay, c_delayDescr, m_delay);
103)   valueUpdate(m_fileMaxScore, c_maxScoreDescr, m_maxScore);
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

104) 
Stefan Schuermans sound support for pong game

Stefan Schuermans authored 5 years ago

105)   // sound name file was modified -> re-read sound name, no other update needed
106)   soundUpdate(m_fileLeftPlayerSound);
107)   soundUpdate(m_fileRightPlayerSound);
108)   soundUpdate(m_fileScoreSound);
109)   soundUpdate(m_fileOtherScoreSound);
110)   soundUpdate(m_fileWinSound);
111)   soundUpdate(m_fileLoseSound);
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

112) }
113) 
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

114) /**
Stefan Schuermans fix comment typo

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

116)  * @param[in] name operator interface name
117)  * @return if accepting new connection is possible
118)  */
119) bool Pong::acceptNewOpConn(const std::string &name)
120) {
Stefan Schuermans add game interlock

Stefan Schuermans authored 5 years ago

121)   // game cannot be activates -> reject connection
122)   if (! canActivate()) {
123)     return false;
124)   }
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

125)   // left player can join if none there yet
Stefan Schuermans pong: configurable speed

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

127)     return true;
128)   }
129)   // right player can join if none there yet
Stefan Schuermans pong: configurable speed

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

155)   }
Stefan Schuermans add op conn close requests

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

157)   else {
Stefan Schuermans add op conn close requests

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

159)     return;
160)   }
Stefan Schuermans pong: activate when player...

Stefan Schuermans authored 5 years ago

161) 
162)   // already active
163)   if (isActive()) {
164)     redraw(); // player color is different for phone / computer
165)   }
Stefan Schuermans add game interlock

Stefan Schuermans authored 5 years ago

166)   // first player joined -> activate
Stefan Schuermans pong: activate when player...

Stefan Schuermans authored 5 years ago

167)   else {
Stefan Schuermans add game interlock

Stefan Schuermans authored 5 years ago

168)     if (! activate()) {
169)       // activation failed (interlock), close connection as soon as possible
170)       requestOpConnClose(pConn);
171)       m_pConnLeft = nullptr;
172)       m_pConnRight = nullptr;
173)     }
Stefan Schuermans pong: activate when player...

Stefan Schuermans authored 5 years ago

174)   }
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

256) }
257) 
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

314) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

315)   // draw ball (blinking if goal delay is active)
316)   if (m_goalDelay <= 0 || (m_goalDelay & 4) == 0) {
Stefan Schuermans fix indentation

Stefan Schuermans authored 5 years ago

317)     pixel(m_ballPosY, m_ballPosX, m_ballColor);
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

318)   }
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

351) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

356)         // maximum score reached
357)         if (m_scoreLeft >= (int)m_maxScore ||
358)             m_scoreRight >= (int)m_maxScore) {
359)           gameOver();
Stefan Schuermans fix comment

Stefan Schuermans authored 5 years ago

360)           return; // gameOver() calls deactivate(), no need to redraw
Stefan Schuermans pong: end game when max sco...

Stefan Schuermans authored 5 years ago

361)         }
362)         // game continues with new ball
363)         else {
364)           startBall();
Stefan Schuermans move time call logic to gam...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

432) {
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

472)   padYmin = ballPosY - m_padSize / 2;
473)   padYmax = ballPosY - (m_padSize - 1) / 2;
474) }
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) /**
477)  * @brief move pad for computer players
478)  * @param[in] padYmin minimum desired y position of pad
479)  * @param[in] padYmax maximum desired y position of pad
480)  * @param[in,out] padPosY y position of pad
481)  */
482) void Pong::computerMovePad(int padYmin, int padYmax, int &padPosY) const
483) {
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

492)   }
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

495)   }
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

497) 
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

542) }
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

563)   }
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

645) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

700)     m_pConnRight->close();
701)     m_pConnRight = NULL;
702)   }
703) 
704)   // deactivate game
705)   deactivate();
706) }
707) 
Stefan Schuermans use same odering in source...

Stefan Schuermans authored 5 years ago

708) /// descriptor for delay value
709) Pong::ValueDescr const Pong::c_delayDescr = { 200, 100, 500 };
710) /// descriptor for maximum score value
711) Pong::ValueDescr const Pong::c_maxScoreDescr = { 9, 1, 99 };
712) 
713) /// operator connection name suffix for left player's connection
714) std::string const Pong::c_opConnSuffixLeft = "/left";
715) /// operator connection name suffix for right player's connection
716) std::string const Pong::c_opConnSuffixRight = "/right";
717)