8c6f3b863a06de3973b3a9e585956a7001c68a43
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 pong: implement phone players

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

30) /// descriptor for delay value
31) Pong::ValueDescr const Pong::c_delayDescr = { 200, 100, 500 };
32) 
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

37) 
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

52)   m_fileDelay(dirBase.getFile("delay")),
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: configurable speed

Stefan Schuermans authored 5 years ago

55)   m_delay(c_delayDescr.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)   }
82) 
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

83)   // cancel time callback request
84)   m_mgrs.m_callMgr.cancelTimeCall(this);
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

85) }
86) 
87) /// check for update of configuration (derived game), return true on update
88) bool Pong::updateConfigGame()
89) {
90)   bool ret = false;
91) 
92)   // color file was modified -> convert color, return true for update
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

96)       colorUpdate(m_fileComputerColor, m_computerColor) ||
97)       colorUpdate(m_fileScoreColor, m_scoreColor) ||
Stefan Schuermans pong: configurable speed

Stefan Schuermans authored 5 years ago

98)       colorUpdate(m_fileGoalColor, m_goalColor) ||
99)       valueUpdate(m_fileDelay, c_delayDescr, m_delay)) {
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

100)     ret = true;
101)   }
102) 
103)   return ret;
104) }
105) 
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

106) /**
107)  * @brief check if accepting new operator connction is possible
108)  * @param[in] name operator interface name
109)  * @return if accepting new connection is possible
110)  */
111) bool Pong::acceptNewOpConn(const std::string &name)
112) {
113)   // left player can join if none there yet
Stefan Schuermans pong: configurable speed

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

115)     return true;
116)   }
117)   // right player can join if none there yet
Stefan Schuermans pong: configurable speed

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

119)     return true;
120)   }
121)   // default: reject connection
122)   return false;
123) }
124) 
125) /**
126)  * @brief new operator connection
127)  * @param[in] name operator interface name
128)  * @param[in] pConn operator connection object
129)  *
130)  * The new connection may not yet be used for sending inside this callback.
131)  */
132) void Pong::newOpConn(const std::string &name, OpConn *pConn)
133) {
134)   // left player joins if none there yet
Stefan Schuermans pong: configurable speed

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

136)     m_pConnLeft = pConn;
137)   }
138)   // right player joins if none there yet
Stefan Schuermans pong: configurable speed

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

140)     m_pConnRight = pConn;
Stefan Schuermans pong: activate when player...

Stefan Schuermans authored 5 years ago

141)   }
142)   // nothing happens
143)   else {
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

144)     return;
145)   }
Stefan Schuermans pong: activate when player...

Stefan Schuermans authored 5 years ago

146) 
147)   // already active
148)   if (isActive()) {
149)     redraw(); // player color is different for phone / computer
150)   }
151)   // first player joined
152)   else {
153)     activate();
154)   }
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

155) }
156) 
157) /**
158)  * @brief key command received on operator connection
159)  * @param[in] pConn operator connection object
160)  * @param[in] key key that was pressed
161)  */
162) void Pong::opConnRecvKey(OpConn *pConn, char key)
163) {
164)   // left player
165)   if (pConn == m_pConnLeft) {
166)     processKey(key, m_leftPosY);
167)   }
168)   // right player
Stefan Schuermans pong: activate when player...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

170)     processKey(key, m_rightPosY);
171)   }
172) }
173) 
174) /**
175)  * @brief play command received on operator connection
176)  * @param[in] pConn operator connection object
177)  * @param[in] sound name of sound to play
178)  */
179) void Pong::opConnRecvPlay(OpConn *pConn, const std::string &sound)
180) {
181)   (void)pConn;
182)   (void)sound;
183) }
184) 
185) /**
186)  * @brief operator connection is closed
187)  * @param[in] pConn operator connection object
188)  *
189)  * The connection may not be used for sending any more in this callback.
190)  */
191) void Pong::opConnClose(OpConn *pConn)
192) {
193)   // left player leaves
194)   if (pConn == m_pConnLeft) {
195)     m_pConnLeft = NULL;
196)   }
197)   // right player leaves
Stefan Schuermans pong: activate when player...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

200)   }
201)   // nothing happens
202)   else {
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

203)     return;
204)   }
Stefan Schuermans pong: activate when player...

Stefan Schuermans authored 5 years ago

205) 
206)   // still a phone player there
207)   if (m_pConnLeft || m_pConnRight) {
208)     redraw(); // player color is different for phone / computer
209)   }
210)   // no phone players left
211)   else {
212)     deactivate();
213)   }
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

214) }
215) 
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

219)   // compute parameters
220)   m_padSize = (m_height + 1) / 3;
221)   m_leftPosY = (m_height - m_padSize) / 2;
222)   m_rightPosY = (m_height - m_padSize) / 2;
Stefan Schuermans pong: make computer slow

Stefan Schuermans authored 5 years ago

223)   m_leftDelay = 0;
224)   m_rightDelay = 0;
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

225) 
226)   // convert colors
227)   color2data(m_fileBallColor, m_ballColor);
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

231)   color2data(m_fileScoreColor, m_scoreColor);
232)   color2data(m_fileGoalColor, m_goalColor);
Stefan Schuermans pong: configurable speed

Stefan Schuermans authored 5 years ago

233)   // get values
234)   valueFromFile(m_fileDelay, c_delayDescr, m_delay);
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

236)   // reset scores
237)   m_scoreLeft = 0;
238)   m_scoreRight = 0;
239) 
240)   // start first ball
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

242) }
243) 
244) /// redraw current game image, expected to call sendFrame() at end
245) void Pong::redraw()
246) {
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

247)   int y, x;
248) 
249)   // draw background
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

252)   // draw middle line: single line on odd width, two dashed lines at even width
253)   for (y = 0; y < m_height; ++y) {
254)     x = (m_width - (y & 1)) / 2;
255)     pixel(y, x, m_lineColor);
256)   }
257) 
Stefan Schuermans pong: display score

Stefan Schuermans authored 5 years ago

258)   // draw score
259)   ColorData const &scoreColor = m_goalDelay <= 0 ? m_scoreColor : m_goalColor;
260)   y = (m_height - 1) / 2;
261)   x = m_width / 4;
262)   number3x5(y, x, 0, 0, m_scoreLeft, scoreColor);
263)   number3x5(y, m_width - 1 - x, 0, 0, m_scoreRight, scoreColor);
264) 
Stefan Schuermans pong: add pads

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

266)   lineVert(m_leftPosY, m_leftPosY + m_padSize - 1, 0,
267)            m_pConnLeft ? m_padColor : m_computerColor);
268)   lineVert(m_rightPosY, m_rightPosY + m_padSize - 1, m_width - 1,
269)            m_pConnRight ? m_padColor : m_computerColor);
Stefan Schuermans pong: add pads

Stefan Schuermans authored 5 years ago

270) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

275) 
276)   // send updated image buffer as frame
277)   sendFrame();
278) }
279) 
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

280) /// callback when requested time reached
281) void Pong::timeCall()
282) {
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

285) 
286)     // computer player: move pads
287)     if (! m_pConnLeft) {
288)       computerLeft();
289)     }
290)     if (! m_pConnRight) {
291)       computerRight();
292)     }
293) 
294)     // bounce ball
295)     bounceBall();
296) 
297)     // move ball
298)     m_ballPosX += m_ballDirX;
299)     m_ballPosY += m_ballDirY;
300) 
301)     // detect goal
302)     detectGoal();
303) 
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

307) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

309) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

310)     // new ball when delay is over
311)     if (m_goalDelay <= 0) {
312)         startBall();
313)         return; // startBall calls redraw() and planTimeCall()
314)     }
315) 
316)   }
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

317) 
318)   // draw and send frame
319)   redraw();
320) 
321)   // request next call if needed
322)   planTimeCall();
323) }
324) 
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

325) /**
326)  * @brief process key received from phone player
327)  * @param[in] key received key from player
328)  * @param[in,out] padPosY y position of player's pad
329)  */
330) void Pong::processKey(char key, int &padPosY)
331) {
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

332)   // do not move pad if goal delay is active
333)   if (m_goalDelay > 0) {
334)     return;
335)   }
336) 
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

337)   // move pad (2 = up, 8 = down), do not move pad out of field
338)   if (key == '2' && padPosY > 0) {
339)     --padPosY;
340)     redraw();
341)   }
342)   else if (key == '8' && padPosY < m_height - m_padSize) {
343)     ++padPosY;
344)     redraw();
345)   }
346) }
347) 
Stefan Schuermans pong: make computer slow

Stefan Schuermans authored 5 years ago

348) /**
349)  * @brief delay processing for computer players
350)  * @param[in,out] delay delay variable of computer player
351)  * @return whether computer player is allowed to move
352)  */
353) bool Pong::computerDelay(int &delay) const
354) 
355) {
356)   // zero delay: generate new delay
357)   if (delay <= 0) {
358)     int avg_steps = (m_height - m_padSize) / 2;
359)     int delay_range = avg_steps > 1 ? m_width / avg_steps: m_width;
360)     delay = rand() % delay_range + delay_range;
361)   }
362) 
363)   // count down delay
364)   --delay;
365) 
366)   // moving allowd if delay expired
367)   return delay <= 0;
368) }
369) 
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

370) /**
371)  * @brief computation of ideal pad position for computer players
372)  * @param[in] padBallX x coordinate of position of ball when hitting the pad
373)  * @param[in] padY current y coordinate of pad
374)  * @param[out] padYmin minimum ideal y position of pad
375)  * @param[out] padYmax maximum ideal y position of pad
376)  */
377) void Pong::computerComputePadPos(int padBallX, int padY,
378)                                  int &padYmin, int &padYmax) const
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

379) {
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

380)   // ball not moving towards pad
381)   if ((padBallX - m_ballPosX) * m_ballDirX <= 0) {
382)     // do not move if ball is still close to pad
383)     if (abs(padBallX - m_ballPosX) <= 2) {
384)       padYmin = padY;
385)       padYmax = padY;
386)       return;
387)     }
388)     // move pad to middle (might be 2 pixels wide)
389)     padYmin = (m_height - m_padSize) / 2;
390)     padYmax = (m_height - m_padSize + 1) / 2;
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

391)     return;
392)   }
393) 
394)   // compute expected ball position at pad
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

395)   int ballPosX = m_ballPosX; // simulate were ball is going
396)   int ballPosY = m_ballPosY;
397)   int ballDirY = m_ballDirY;
398)   while ((padBallX - ballPosX) * m_ballDirX > 0) { // while moving to pad
399)     int deltaX = padBallX - ballPosX;
400)     int deltaY = deltaX * m_ballDirX * ballDirY;
401)     if (deltaY < -ballPosY) {
402)       deltaY = -ballPosY;
403)       ballPosX += deltaY * m_ballDirX * ballDirY;
404)       ballPosY = 0;
405)       ballDirY = 1;
406)     }
407)     else if (deltaY > m_height - 1 - ballPosY) {
408)       deltaY = m_height - 1 - ballPosY;
409)       ballPosX += deltaY * m_ballDirX * ballDirY;
410)       ballPosY = m_height - 1;
411)       ballDirY = -1;
412)     } else {
413)       ballPosX += deltaX;
414)       ballPosY += deltaY;
415)     }
416)   }
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

419)   padYmin = ballPosY - m_padSize / 2;
420)   padYmax = ballPosY - (m_padSize - 1) / 2;
421) }
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

422) 
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

423) /**
424)  * @brief move pad for computer players
425)  * @param[in] padYmin minimum desired y position of pad
426)  * @param[in] padYmax maximum desired y position of pad
427)  * @param[in,out] padPosY y position of pad
428)  */
429) void Pong::computerMovePad(int padYmin, int padYmax, int &padPosY) const
430) {
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

431)   // do not move pad if goal delay is active
432)   if (m_goalDelay > 0) {
433)     return;
434)   }
435) 
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

439)   }
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

442)   }
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

444) 
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

445) /// computer player for left pad
446) void Pong::computerLeft()
447) {
Stefan Schuermans pong: make computer slow

Stefan Schuermans authored 5 years ago

448)   if (computerDelay(m_leftDelay)) {
449)     int padYmin, padYmax;
450)     computerComputePadPos(1, m_leftPosY, padYmin, padYmax);
451)     computerMovePad(padYmin, padYmax, m_leftPosY);
452)   }
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

453) }
454) 
455) /// computer player for right pad
456) void Pong::computerRight()
457) {
Stefan Schuermans pong: make computer slow

Stefan Schuermans authored 5 years ago

458)   if (computerDelay(m_rightDelay)) {
459)     int padYmin, padYmax;
460)     computerComputePadPos(m_width - 2, m_rightPosY, padYmin, padYmax);
461)     computerMovePad(padYmin, padYmax, m_rightPosY);
462)   }
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

463) }
464) 
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

465) /// bounce ball
466) void Pong::bounceBall()
467) {
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

469)   bounceBallLeft();
470)   bounceBallRight();
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

472) }
473) 
474) /// bounce ball at sides
475) void Pong::bounceBallSide()
476) {
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

477)   if (m_ballPosY <= 0 && m_ballDirY < 0) {
478)     m_ballDirY = 1;
479)   }
480)   if (m_ballPosY >= m_height - 1 && m_ballDirY > 0) {
481)     m_ballDirY = -1;
482)   }
483)   if (m_ballPosX <= 0 && m_ballDirX < 0) {
484)     m_ballDirX = 1;
485)   }
486)   if (m_ballPosX >= m_width - 1 && m_ballDirX > 0) {
487)     m_ballDirX = -1;
488)   }
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

489) }
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

491) /// bounce ball at left pad
492) void Pong::bounceBallLeft()
493) {
494)   if (m_ballPosX != 1 || m_ballDirX >= 0) {
495)     return;
Stefan Schuermans pong: add pads

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

498)   // top corner
499)   if (m_ballPosY == m_leftPosY - 1 && m_ballDirY > 0) {
500)     m_ballDirX = 1;
501)     m_ballDirY = -1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

503)   }
504) 
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

505)   // bottom corner
506)   else if (m_ballPosY == m_leftPosY + m_padSize && m_ballDirY < 0) {
507)     m_ballDirX = 1;
508)     m_ballDirY = 1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

510)   }
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

512)   // pad edge
513)   else if (m_ballPosY >= m_leftPosY &&
514)            m_ballPosY < m_leftPosY + m_padSize) {
515)     m_ballDirX = 1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

517)   }
518) }
519) 
520) /// bounce ball at right pad
521) void Pong::bounceBallRight()
522) {
523)   if (m_ballPosX != m_width - 2 || m_ballDirX <= 0) {
524)     return;
525)   }
526) 
527)   // top corner
528)   if (m_ballPosY == m_rightPosY - 1 && m_ballDirY > 0) {
529)     m_ballDirX = -1;
530)     m_ballDirY = -1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

532)   }
533) 
534)   // bottom corner
535)   else if (m_ballPosY == m_rightPosY + m_padSize && m_ballDirY < 0) {
536)     m_ballDirX = -1;
537)     m_ballDirY = 1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

539)   }
540) 
541)   // pad edge
542)   else if (m_ballPosY >= m_rightPosY &&
543)            m_ballPosY < m_rightPosY + m_padSize) {
544)     m_ballDirX = -1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

545)     ++m_bounceCnt;
546)   }
547) }
548) 
549) /// detect goal
550) void Pong::detectGoal()
551) {
552)   static int goalBlinkCnt = 3;
553)   static int goalDelay = goalBlinkCnt * 8 + 3;
554) 
555)   // ball at far left - goal for right player
556)   if (m_ballPosX == 0) {
557)     m_goalDelay = goalDelay;
558)     ++m_scoreRight;
559)   }
560) 
561)   // ball at far right - goal for left player
562)   else if (m_ballPosX == m_width - 1) {
563)     m_goalDelay = goalDelay;
564)     ++m_scoreLeft;
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

565)   }
566) }
567) 
568) /// request next time call - or cancel request if not needed
569) void Pong::planTimeCall()
570) {
Stefan Schuermans pong: activate when player...

Stefan Schuermans authored 5 years ago

571)   // no time call needed if not active
572)   if (! isActive()) {
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

573)     m_mgrs.m_callMgr.cancelTimeCall(this);
574)     return;
575)   }
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

576) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

581) 
582)   // request next time call
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

584)   stepTime.fromFloatSec(interval);
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

585)   m_mgrs.m_callMgr.requestTimeCall(this, Time::now() + stepTime);
586) }
587) 
588) /// start ball
589) void Pong::startBall()
590) {
591)   // ball starts horizontally at middle of field, vertically random
592)   m_ballPosX = (m_width - (rand() & 1)) / 2;
593)   m_ballPosY = rand() % m_height;
594)   // random diagonal direction
595)   m_ballDirX = (rand() & 1) * 2 - 1;
596)   m_ballDirY = (rand() & 1) * 2 - 1;
597) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

598)   // no delays, ball has not bounced at pad
599)   m_leftDelay = 0;
600)   m_rightDelay = 0;
601)   m_goalDelay = 0;
602)   m_bounceCnt = 0;
603) 
604)   // draw and send frame
605)   redraw();
606) 
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

607)   // request first time call if needed
608)   planTimeCall();
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

609) }
610)