8432360ab9252a32f98608fe63775fc9aafb7f11
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")),
46)   m_ballColor(), m_lineColor(), m_padColor(), m_computerColor(),
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

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

Stefan Schuermans authored 5 years ago

51) {
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

55) }
56) 
57) /// virtual destructor
58) Pong::~Pong()
59) {
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

86)       colorUpdate(m_filePadColor, m_padColor) ||
87)       colorUpdate(m_fileComputerColor, m_computerColor)) {
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

88)     ret = true;
89)   }
90) 
91)   return ret;
92) }
93) 
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

129)   }
130)   // nothing happens
131)   else {
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

132)     return;
133)   }
Stefan Schuermans pong: activate when player...

Stefan Schuermans authored 5 years ago

134) 
135)   // already active
136)   if (isActive()) {
137)     redraw(); // player color is different for phone / computer
138)   }
139)   // first player joined
140)   else {
141)     activate();
142)   }
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

188)   }
189)   // nothing happens
190)   else {
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

191)     return;
192)   }
Stefan Schuermans pong: activate when player...

Stefan Schuermans authored 5 years ago

193) 
194)   // still a phone player there
195)   if (m_pConnLeft || m_pConnRight) {
196)     redraw(); // player color is different for phone / computer
197)   }
198)   // no phone players left
199)   else {
200)     deactivate();
201)   }
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

202) }
203) 
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

207)   // compute parameters
208)   m_padSize = (m_height + 1) / 3;
209)   m_leftPosY = (m_height - m_padSize) / 2;
210)   m_rightPosY = (m_height - m_padSize) / 2;
Stefan Schuermans pong: make computer slow

Stefan Schuermans authored 5 years ago

211)   m_leftDelay = 0;
212)   m_rightDelay = 0;
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

213) 
214)   // convert colors
215)   color2data(m_fileBallColor, m_ballColor);
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

218)   color2data(m_fileComputerColor, m_computerColor);
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

220)   // reset scores
221)   m_scoreLeft = 0;
222)   m_scoreRight = 0;
223) 
224)   // start first ball
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

226) }
227) 
228) /// redraw current game image, expected to call sendFrame() at end
229) void Pong::redraw()
230) {
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

231)   int y, x;
232) 
233)   // draw background
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

236)   // draw middle line: single line on odd width, two dashed lines at even width
237)   for (y = 0; y < m_height; ++y) {
238)     x = (m_width - (y & 1)) / 2;
239)     pixel(y, x, m_lineColor);
240)   }
241) 
Stefan Schuermans pong: add pads

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

243)   lineVert(m_leftPosY, m_leftPosY + m_padSize - 1, 0,
244)            m_pConnLeft ? m_padColor : m_computerColor);
245)   lineVert(m_rightPosY, m_rightPosY + m_padSize - 1, m_width - 1,
246)            m_pConnRight ? m_padColor : m_computerColor);
Stefan Schuermans pong: add pads

Stefan Schuermans authored 5 years ago

247) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

252) 
253)   // send updated image buffer as frame
254)   sendFrame();
255) }
256) 
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

257) /// callback when requested time reached
258) void Pong::timeCall()
259) {
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

262) 
263)     // computer player: move pads
264)     if (! m_pConnLeft) {
265)       computerLeft();
266)     }
267)     if (! m_pConnRight) {
268)       computerRight();
269)     }
270) 
271)     // bounce ball
272)     bounceBall();
273) 
274)     // move ball
275)     m_ballPosX += m_ballDirX;
276)     m_ballPosY += m_ballDirY;
277) 
278)     // detect goal
279)     detectGoal();
280) 
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

284) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

286) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

287)     // new ball when delay is over
288)     if (m_goalDelay <= 0) {
289)         startBall();
290)         return; // startBall calls redraw() and planTimeCall()
291)     }
292) 
293)   }
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

294) 
295)   // draw and send frame
296)   redraw();
297) 
298)   // request next call if needed
299)   planTimeCall();
300) }
301) 
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

302) /**
303)  * @brief process key received from phone player
304)  * @param[in] key received key from player
305)  * @param[in,out] padPosY y position of player's pad
306)  */
307) void Pong::processKey(char key, int &padPosY)
308) {
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

309)   // do not move pad if goal delay is active
310)   if (m_goalDelay > 0) {
311)     return;
312)   }
313) 
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

314)   // move pad (2 = up, 8 = down), do not move pad out of field
315)   if (key == '2' && padPosY > 0) {
316)     --padPosY;
317)     redraw();
318)   }
319)   else if (key == '8' && padPosY < m_height - m_padSize) {
320)     ++padPosY;
321)     redraw();
322)   }
323) }
324) 
Stefan Schuermans pong: make computer slow

Stefan Schuermans authored 5 years ago

325) /**
326)  * @brief delay processing for computer players
327)  * @param[in,out] delay delay variable of computer player
328)  * @return whether computer player is allowed to move
329)  */
330) bool Pong::computerDelay(int &delay) const
331) 
332) {
333)   // zero delay: generate new delay
334)   if (delay <= 0) {
335)     int avg_steps = (m_height - m_padSize) / 2;
336)     int delay_range = avg_steps > 1 ? m_width / avg_steps: m_width;
337)     delay = rand() % delay_range + delay_range;
338)   }
339) 
340)   // count down delay
341)   --delay;
342) 
343)   // moving allowd if delay expired
344)   return delay <= 0;
345) }
346) 
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

347) /**
348)  * @brief computation of ideal pad position for computer players
349)  * @param[in] padBallX x coordinate of position of ball when hitting the pad
350)  * @param[in] padY current y coordinate of pad
351)  * @param[out] padYmin minimum ideal y position of pad
352)  * @param[out] padYmax maximum ideal y position of pad
353)  */
354) void Pong::computerComputePadPos(int padBallX, int padY,
355)                                  int &padYmin, int &padYmax) const
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

356) {
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

357)   // ball not moving towards pad
358)   if ((padBallX - m_ballPosX) * m_ballDirX <= 0) {
359)     // do not move if ball is still close to pad
360)     if (abs(padBallX - m_ballPosX) <= 2) {
361)       padYmin = padY;
362)       padYmax = padY;
363)       return;
364)     }
365)     // move pad to middle (might be 2 pixels wide)
366)     padYmin = (m_height - m_padSize) / 2;
367)     padYmax = (m_height - m_padSize + 1) / 2;
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

368)     return;
369)   }
370) 
371)   // compute expected ball position at pad
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

372)   int ballPosX = m_ballPosX; // simulate were ball is going
373)   int ballPosY = m_ballPosY;
374)   int ballDirY = m_ballDirY;
375)   while ((padBallX - ballPosX) * m_ballDirX > 0) { // while moving to pad
376)     int deltaX = padBallX - ballPosX;
377)     int deltaY = deltaX * m_ballDirX * ballDirY;
378)     if (deltaY < -ballPosY) {
379)       deltaY = -ballPosY;
380)       ballPosX += deltaY * m_ballDirX * ballDirY;
381)       ballPosY = 0;
382)       ballDirY = 1;
383)     }
384)     else if (deltaY > m_height - 1 - ballPosY) {
385)       deltaY = m_height - 1 - ballPosY;
386)       ballPosX += deltaY * m_ballDirX * ballDirY;
387)       ballPosY = m_height - 1;
388)       ballDirY = -1;
389)     } else {
390)       ballPosX += deltaX;
391)       ballPosY += deltaY;
392)     }
393)   }
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

396)   padYmin = ballPosY - m_padSize / 2;
397)   padYmax = ballPosY - (m_padSize - 1) / 2;
398) }
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

399) 
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

400) /**
401)  * @brief move pad for computer players
402)  * @param[in] padYmin minimum desired y position of pad
403)  * @param[in] padYmax maximum desired y position of pad
404)  * @param[in,out] padPosY y position of pad
405)  */
406) void Pong::computerMovePad(int padYmin, int padYmax, int &padPosY) const
407) {
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

408)   // do not move pad if goal delay is active
409)   if (m_goalDelay > 0) {
410)     return;
411)   }
412) 
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

416)   }
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

419)   }
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

421) 
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

422) /// computer player for left pad
423) void Pong::computerLeft()
424) {
Stefan Schuermans pong: make computer slow

Stefan Schuermans authored 5 years ago

425)   if (computerDelay(m_leftDelay)) {
426)     int padYmin, padYmax;
427)     computerComputePadPos(1, m_leftPosY, padYmin, padYmax);
428)     computerMovePad(padYmin, padYmax, m_leftPosY);
429)   }
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

430) }
431) 
432) /// computer player for right pad
433) void Pong::computerRight()
434) {
Stefan Schuermans pong: make computer slow

Stefan Schuermans authored 5 years ago

435)   if (computerDelay(m_rightDelay)) {
436)     int padYmin, padYmax;
437)     computerComputePadPos(m_width - 2, m_rightPosY, padYmin, padYmax);
438)     computerMovePad(padYmin, padYmax, m_rightPosY);
439)   }
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

440) }
441) 
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

442) /// bounce ball
443) void Pong::bounceBall()
444) {
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

446)   bounceBallLeft();
447)   bounceBallRight();
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

449) }
450) 
451) /// bounce ball at sides
452) void Pong::bounceBallSide()
453) {
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

454)   if (m_ballPosY <= 0 && m_ballDirY < 0) {
455)     m_ballDirY = 1;
456)   }
457)   if (m_ballPosY >= m_height - 1 && m_ballDirY > 0) {
458)     m_ballDirY = -1;
459)   }
460)   if (m_ballPosX <= 0 && m_ballDirX < 0) {
461)     m_ballDirX = 1;
462)   }
463)   if (m_ballPosX >= m_width - 1 && m_ballDirX > 0) {
464)     m_ballDirX = -1;
465)   }
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

466) }
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

468) /// bounce ball at left pad
469) void Pong::bounceBallLeft()
470) {
471)   if (m_ballPosX != 1 || m_ballDirX >= 0) {
472)     return;
Stefan Schuermans pong: add pads

Stefan Schuermans authored 5 years ago

473)   }
474) 
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

475)   // top corner
476)   if (m_ballPosY == m_leftPosY - 1 && m_ballDirY > 0) {
477)     m_ballDirX = 1;
478)     m_ballDirY = -1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

482)   // bottom corner
483)   else if (m_ballPosY == m_leftPosY + m_padSize && m_ballDirY < 0) {
484)     m_ballDirX = 1;
485)     m_ballDirY = 1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

487)   }
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

489)   // pad edge
490)   else if (m_ballPosY >= m_leftPosY &&
491)            m_ballPosY < m_leftPosY + m_padSize) {
492)     m_ballDirX = 1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

494)   }
495) }
496) 
497) /// bounce ball at right pad
498) void Pong::bounceBallRight()
499) {
500)   if (m_ballPosX != m_width - 2 || m_ballDirX <= 0) {
501)     return;
502)   }
503) 
504)   // top corner
505)   if (m_ballPosY == m_rightPosY - 1 && m_ballDirY > 0) {
506)     m_ballDirX = -1;
507)     m_ballDirY = -1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

509)   }
510) 
511)   // bottom corner
512)   else if (m_ballPosY == m_rightPosY + m_padSize && m_ballDirY < 0) {
513)     m_ballDirX = -1;
514)     m_ballDirY = 1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

516)   }
517) 
518)   // pad edge
519)   else if (m_ballPosY >= m_rightPosY &&
520)            m_ballPosY < m_rightPosY + m_padSize) {
521)     m_ballDirX = -1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

522)     ++m_bounceCnt;
523)   }
524) }
525) 
526) /// detect goal
527) void Pong::detectGoal()
528) {
529)   static int goalBlinkCnt = 3;
530)   static int goalDelay = goalBlinkCnt * 8 + 3;
531) 
532)   // ball at far left - goal for right player
533)   if (m_ballPosX == 0) {
534)     m_goalDelay = goalDelay;
535)     ++m_scoreRight;
536)   }
537) 
538)   // ball at far right - goal for left player
539)   else if (m_ballPosX == m_width - 1) {
540)     m_goalDelay = goalDelay;
541)     ++m_scoreLeft;
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

542)   }
543) }
544) 
545) /// request next time call - or cancel request if not needed
546) void Pong::planTimeCall()
547) {
Stefan Schuermans pong: activate when player...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

550)     m_mgrs.m_callMgr.cancelTimeCall(this);
551)     return;
552)   }
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

553) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

554)   // compute interval based on score and bounce count
555)   float speedup = 10 * (m_scoreLeft + m_scoreRight) + m_bounceCnt;
556)   float interval = 0.05f + 0.1f * expf(-0.03f * speedup);
557) 
558)   // request next time call
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

561)   m_mgrs.m_callMgr.requestTimeCall(this, Time::now() + stepTime);
562) }
563) 
564) /// start ball
565) void Pong::startBall()
566) {
567)   // ball starts horizontally at middle of field, vertically random
568)   m_ballPosX = (m_width - (rand() & 1)) / 2;
569)   m_ballPosY = rand() % m_height;
570)   // random diagonal direction
571)   m_ballDirX = (rand() & 1) * 2 - 1;
572)   m_ballDirY = (rand() & 1) * 2 - 1;
573) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

574)   // no delays, ball has not bounced at pad
575)   m_leftDelay = 0;
576)   m_rightDelay = 0;
577)   m_goalDelay = 0;
578)   m_bounceCnt = 0;
579) 
580)   // draw and send frame
581)   redraw();
582) 
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

585) }
586)