3e790c77486205e58a0bb765ac95289617e5b3b5
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 begin of Pong game

Stefan Schuermans authored 5 years ago

26) 
27) namespace Blinker {
28) 
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

29) /// operator connection name suffix for left player's connection
30) std::string const Pong::OpConnSuffixLeft = "/left";
31) /// operator connection name suffix for right player's connection
32) std::string const Pong::OpConnSuffixRight = "/right";
33) 
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

46)   m_fileScoreColor(dirBase.getFile("scoreColor")),
47)   m_fileGoalColor(dirBase.getFile("goalColor")),
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

49)   m_scoreColor(), m_goalColor(),
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

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

Stefan Schuermans authored 5 years ago

54) {
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

55)   // open operator connection interfaces for left and right player
56)   m_mgrs.m_opMgr.open(m_name + OpConnSuffixLeft, this);
57)   m_mgrs.m_opMgr.open(m_name + OpConnSuffixRight, this);
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

58) }
59) 
60) /// virtual destructor
61) Pong::~Pong()
62) {
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

63)   // close operator connection interfaces
64)   m_mgrs.m_opMgr.close(m_name + OpConnSuffixLeft);
65)   m_mgrs.m_opMgr.close(m_name + OpConnSuffixRight);
66) 
67)   // close open operator connections
68)   if (m_pConnLeft) {
69)     m_pConnLeft->close();
70)     m_pConnLeft = NULL;
71)   }
72)   if (m_pConnRight) {
73)     m_pConnRight->close();
74)     m_pConnRight = NULL;
75)   }
76) 
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

79) }
80) 
81) /// check for update of configuration (derived game), return true on update
82) bool Pong::updateConfigGame()
83) {
84)   bool ret = false;
85) 
86)   // color file was modified -> convert color, return true for update
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

90)       colorUpdate(m_fileComputerColor, m_computerColor) ||
91)       colorUpdate(m_fileScoreColor, m_scoreColor) ||
92)       colorUpdate(m_fileGoalColor, m_goalColor)) {
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

93)     ret = true;
94)   }
95) 
96)   return ret;
97) }
98) 
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

99) /**
100)  * @brief check if accepting new operator connction is possible
101)  * @param[in] name operator interface name
102)  * @return if accepting new connection is possible
103)  */
104) bool Pong::acceptNewOpConn(const std::string &name)
105) {
106)   // left player can join if none there yet
107)   if (name == m_name + OpConnSuffixLeft && ! m_pConnLeft) {
108)     return true;
109)   }
110)   // right player can join if none there yet
111)   if (name == m_name + OpConnSuffixRight && ! m_pConnRight) {
112)     return true;
113)   }
114)   // default: reject connection
115)   return false;
116) }
117) 
118) /**
119)  * @brief new operator connection
120)  * @param[in] name operator interface name
121)  * @param[in] pConn operator connection object
122)  *
123)  * The new connection may not yet be used for sending inside this callback.
124)  */
125) void Pong::newOpConn(const std::string &name, OpConn *pConn)
126) {
127)   // left player joins if none there yet
128)   if (name == m_name + OpConnSuffixLeft && ! m_pConnLeft) {
129)     m_pConnLeft = pConn;
130)   }
131)   // right player joins if none there yet
Stefan Schuermans pong: activate when player...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

134)   }
135)   // nothing happens
136)   else {
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

137)     return;
138)   }
Stefan Schuermans pong: activate when player...

Stefan Schuermans authored 5 years ago

139) 
140)   // already active
141)   if (isActive()) {
142)     redraw(); // player color is different for phone / computer
143)   }
144)   // first player joined
145)   else {
146)     activate();
147)   }
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

148) }
149) 
150) /**
151)  * @brief key command received on operator connection
152)  * @param[in] pConn operator connection object
153)  * @param[in] key key that was pressed
154)  */
155) void Pong::opConnRecvKey(OpConn *pConn, char key)
156) {
157)   // left player
158)   if (pConn == m_pConnLeft) {
159)     processKey(key, m_leftPosY);
160)   }
161)   // right player
Stefan Schuermans pong: activate when player...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

193)   }
194)   // nothing happens
195)   else {
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

196)     return;
197)   }
Stefan Schuermans pong: activate when player...

Stefan Schuermans authored 5 years ago

198) 
199)   // still a phone player there
200)   if (m_pConnLeft || m_pConnRight) {
201)     redraw(); // player color is different for phone / computer
202)   }
203)   // no phone players left
204)   else {
205)     deactivate();
206)   }
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

207) }
208) 
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

212)   // compute parameters
213)   m_padSize = (m_height + 1) / 3;
214)   m_leftPosY = (m_height - m_padSize) / 2;
215)   m_rightPosY = (m_height - m_padSize) / 2;
Stefan Schuermans pong: make computer slow

Stefan Schuermans authored 5 years ago

216)   m_leftDelay = 0;
217)   m_rightDelay = 0;
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

218) 
219)   // convert colors
220)   color2data(m_fileBallColor, m_ballColor);
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

224)   color2data(m_fileScoreColor, m_scoreColor);
225)   color2data(m_fileGoalColor, m_goalColor);
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

227)   // reset scores
228)   m_scoreLeft = 0;
229)   m_scoreRight = 0;
230) 
231)   // start first ball
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

233) }
234) 
235) /// redraw current game image, expected to call sendFrame() at end
236) void Pong::redraw()
237) {
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

238)   int y, x;
239) 
240)   // draw background
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

243)   // draw middle line: single line on odd width, two dashed lines at even width
244)   for (y = 0; y < m_height; ++y) {
245)     x = (m_width - (y & 1)) / 2;
246)     pixel(y, x, m_lineColor);
247)   }
248) 
Stefan Schuermans pong: display score

Stefan Schuermans authored 5 years ago

249)   // draw score
250)   ColorData const &scoreColor = m_goalDelay <= 0 ? m_scoreColor : m_goalColor;
251)   y = (m_height - 1) / 2;
252)   x = m_width / 4;
253)   number3x5(y, x, 0, 0, m_scoreLeft, scoreColor);
254)   number3x5(y, m_width - 1 - x, 0, 0, m_scoreRight, scoreColor);
255) 
Stefan Schuermans pong: add pads

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

257)   lineVert(m_leftPosY, m_leftPosY + m_padSize - 1, 0,
258)            m_pConnLeft ? m_padColor : m_computerColor);
259)   lineVert(m_rightPosY, m_rightPosY + m_padSize - 1, m_width - 1,
260)            m_pConnRight ? m_padColor : m_computerColor);
Stefan Schuermans pong: add pads

Stefan Schuermans authored 5 years ago

261) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

266) 
267)   // send updated image buffer as frame
268)   sendFrame();
269) }
270) 
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

271) /// callback when requested time reached
272) void Pong::timeCall()
273) {
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

276) 
277)     // computer player: move pads
278)     if (! m_pConnLeft) {
279)       computerLeft();
280)     }
281)     if (! m_pConnRight) {
282)       computerRight();
283)     }
284) 
285)     // bounce ball
286)     bounceBall();
287) 
288)     // move ball
289)     m_ballPosX += m_ballDirX;
290)     m_ballPosY += m_ballDirY;
291) 
292)     // detect goal
293)     detectGoal();
294) 
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

298) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

300) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

301)     // new ball when delay is over
302)     if (m_goalDelay <= 0) {
303)         startBall();
304)         return; // startBall calls redraw() and planTimeCall()
305)     }
306) 
307)   }
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

308) 
309)   // draw and send frame
310)   redraw();
311) 
312)   // request next call if needed
313)   planTimeCall();
314) }
315) 
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

316) /**
317)  * @brief process key received from phone player
318)  * @param[in] key received key from player
319)  * @param[in,out] padPosY y position of player's pad
320)  */
321) void Pong::processKey(char key, int &padPosY)
322) {
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

323)   // do not move pad if goal delay is active
324)   if (m_goalDelay > 0) {
325)     return;
326)   }
327) 
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

328)   // move pad (2 = up, 8 = down), do not move pad out of field
329)   if (key == '2' && padPosY > 0) {
330)     --padPosY;
331)     redraw();
332)   }
333)   else if (key == '8' && padPosY < m_height - m_padSize) {
334)     ++padPosY;
335)     redraw();
336)   }
337) }
338) 
Stefan Schuermans pong: make computer slow

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

361) /**
362)  * @brief computation of ideal pad position for computer players
363)  * @param[in] padBallX x coordinate of position of ball when hitting the pad
364)  * @param[in] padY current y coordinate of pad
365)  * @param[out] padYmin minimum ideal y position of pad
366)  * @param[out] padYmax maximum ideal y position of pad
367)  */
368) void Pong::computerComputePadPos(int padBallX, int padY,
369)                                  int &padYmin, int &padYmax) const
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

370) {
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

371)   // ball not moving towards pad
372)   if ((padBallX - m_ballPosX) * m_ballDirX <= 0) {
373)     // do not move if ball is still close to pad
374)     if (abs(padBallX - m_ballPosX) <= 2) {
375)       padYmin = padY;
376)       padYmax = padY;
377)       return;
378)     }
379)     // move pad to middle (might be 2 pixels wide)
380)     padYmin = (m_height - m_padSize) / 2;
381)     padYmax = (m_height - m_padSize + 1) / 2;
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

382)     return;
383)   }
384) 
385)   // compute expected ball position at pad
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

386)   int ballPosX = m_ballPosX; // simulate were ball is going
387)   int ballPosY = m_ballPosY;
388)   int ballDirY = m_ballDirY;
389)   while ((padBallX - ballPosX) * m_ballDirX > 0) { // while moving to pad
390)     int deltaX = padBallX - ballPosX;
391)     int deltaY = deltaX * m_ballDirX * ballDirY;
392)     if (deltaY < -ballPosY) {
393)       deltaY = -ballPosY;
394)       ballPosX += deltaY * m_ballDirX * ballDirY;
395)       ballPosY = 0;
396)       ballDirY = 1;
397)     }
398)     else if (deltaY > m_height - 1 - ballPosY) {
399)       deltaY = m_height - 1 - ballPosY;
400)       ballPosX += deltaY * m_ballDirX * ballDirY;
401)       ballPosY = m_height - 1;
402)       ballDirY = -1;
403)     } else {
404)       ballPosX += deltaX;
405)       ballPosY += deltaY;
406)     }
407)   }
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

410)   padYmin = ballPosY - m_padSize / 2;
411)   padYmax = ballPosY - (m_padSize - 1) / 2;
412) }
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

413) 
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

414) /**
415)  * @brief move pad for computer players
416)  * @param[in] padYmin minimum desired y position of pad
417)  * @param[in] padYmax maximum desired y position of pad
418)  * @param[in,out] padPosY y position of pad
419)  */
420) void Pong::computerMovePad(int padYmin, int padYmax, int &padPosY) const
421) {
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

422)   // do not move pad if goal delay is active
423)   if (m_goalDelay > 0) {
424)     return;
425)   }
426) 
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

430)   }
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

433)   }
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

435) 
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

436) /// computer player for left pad
437) void Pong::computerLeft()
438) {
Stefan Schuermans pong: make computer slow

Stefan Schuermans authored 5 years ago

439)   if (computerDelay(m_leftDelay)) {
440)     int padYmin, padYmax;
441)     computerComputePadPos(1, m_leftPosY, padYmin, padYmax);
442)     computerMovePad(padYmin, padYmax, m_leftPosY);
443)   }
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

444) }
445) 
446) /// computer player for right pad
447) void Pong::computerRight()
448) {
Stefan Schuermans pong: make computer slow

Stefan Schuermans authored 5 years ago

449)   if (computerDelay(m_rightDelay)) {
450)     int padYmin, padYmax;
451)     computerComputePadPos(m_width - 2, m_rightPosY, padYmin, padYmax);
452)     computerMovePad(padYmin, padYmax, m_rightPosY);
453)   }
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

454) }
455) 
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

456) /// bounce ball
457) void Pong::bounceBall()
458) {
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

460)   bounceBallLeft();
461)   bounceBallRight();
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

463) }
464) 
465) /// bounce ball at sides
466) void Pong::bounceBallSide()
467) {
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

468)   if (m_ballPosY <= 0 && m_ballDirY < 0) {
469)     m_ballDirY = 1;
470)   }
471)   if (m_ballPosY >= m_height - 1 && m_ballDirY > 0) {
472)     m_ballDirY = -1;
473)   }
474)   if (m_ballPosX <= 0 && m_ballDirX < 0) {
475)     m_ballDirX = 1;
476)   }
477)   if (m_ballPosX >= m_width - 1 && m_ballDirX > 0) {
478)     m_ballDirX = -1;
479)   }
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

480) }
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

482) /// bounce ball at left pad
483) void Pong::bounceBallLeft()
484) {
485)   if (m_ballPosX != 1 || m_ballDirX >= 0) {
486)     return;
Stefan Schuermans pong: add pads

Stefan Schuermans authored 5 years ago

487)   }
488) 
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

489)   // top corner
490)   if (m_ballPosY == m_leftPosY - 1 && m_ballDirY > 0) {
491)     m_ballDirX = 1;
492)     m_ballDirY = -1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

494)   }
495) 
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

496)   // bottom corner
497)   else if (m_ballPosY == m_leftPosY + m_padSize && m_ballDirY < 0) {
498)     m_ballDirX = 1;
499)     m_ballDirY = 1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

501)   }
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

503)   // pad edge
504)   else if (m_ballPosY >= m_leftPosY &&
505)            m_ballPosY < m_leftPosY + m_padSize) {
506)     m_ballDirX = 1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

508)   }
509) }
510) 
511) /// bounce ball at right pad
512) void Pong::bounceBallRight()
513) {
514)   if (m_ballPosX != m_width - 2 || m_ballDirX <= 0) {
515)     return;
516)   }
517) 
518)   // top corner
519)   if (m_ballPosY == m_rightPosY - 1 && m_ballDirY > 0) {
520)     m_ballDirX = -1;
521)     m_ballDirY = -1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

523)   }
524) 
525)   // bottom corner
526)   else if (m_ballPosY == m_rightPosY + m_padSize && m_ballDirY < 0) {
527)     m_ballDirX = -1;
528)     m_ballDirY = 1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

530)   }
531) 
532)   // pad edge
533)   else if (m_ballPosY >= m_rightPosY &&
534)            m_ballPosY < m_rightPosY + m_padSize) {
535)     m_ballDirX = -1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

536)     ++m_bounceCnt;
537)   }
538) }
539) 
540) /// detect goal
541) void Pong::detectGoal()
542) {
543)   static int goalBlinkCnt = 3;
544)   static int goalDelay = goalBlinkCnt * 8 + 3;
545) 
546)   // ball at far left - goal for right player
547)   if (m_ballPosX == 0) {
548)     m_goalDelay = goalDelay;
549)     ++m_scoreRight;
550)   }
551) 
552)   // ball at far right - goal for left player
553)   else if (m_ballPosX == m_width - 1) {
554)     m_goalDelay = goalDelay;
555)     ++m_scoreLeft;
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

556)   }
557) }
558) 
559) /// request next time call - or cancel request if not needed
560) void Pong::planTimeCall()
561) {
Stefan Schuermans pong: activate when player...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

564)     m_mgrs.m_callMgr.cancelTimeCall(this);
565)     return;
566)   }
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

567) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

568)   // compute interval based on score and bounce count
569)   float speedup = 10 * (m_scoreLeft + m_scoreRight) + m_bounceCnt;
570)   float interval = 0.05f + 0.1f * expf(-0.03f * speedup);
571) 
572)   // request next time call
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

575)   m_mgrs.m_callMgr.requestTimeCall(this, Time::now() + stepTime);
576) }
577) 
578) /// start ball
579) void Pong::startBall()
580) {
581)   // ball starts horizontally at middle of field, vertically random
582)   m_ballPosX = (m_width - (rand() & 1)) / 2;
583)   m_ballPosY = rand() % m_height;
584)   // random diagonal direction
585)   m_ballDirX = (rand() & 1) * 2 - 1;
586)   m_ballDirY = (rand() & 1) * 2 - 1;
587) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

588)   // no delays, ball has not bounced at pad
589)   m_leftDelay = 0;
590)   m_rightDelay = 0;
591)   m_goalDelay = 0;
592)   m_bounceCnt = 0;
593) 
594)   // draw and send frame
595)   redraw();
596) 
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

599) }
600)