94a4881fc4fd3c22a37d348800dfd13a9f9d4a8e
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);
55) 
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

56)   // FIXME: activate at begin for initial development only
57)   activate();
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) ||
90)       colorUpdate(m_fileComputerColor, m_computerColor)) {
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

97) /**
98)  * @brief check if accepting new operator connction is possible
99)  * @param[in] name operator interface name
100)  * @return if accepting new connection is possible
101)  */
102) bool Pong::acceptNewOpConn(const std::string &name)
103) {
104)   // left player can join if none there yet
105)   if (name == m_name + OpConnSuffixLeft && ! m_pConnLeft) {
106)     return true;
107)   }
108)   // right player can join if none there yet
109)   if (name == m_name + OpConnSuffixRight && ! m_pConnRight) {
110)     return true;
111)   }
112)   // default: reject connection
113)   return false;
114) }
115) 
116) /**
117)  * @brief new operator connection
118)  * @param[in] name operator interface name
119)  * @param[in] pConn operator connection object
120)  *
121)  * The new connection may not yet be used for sending inside this callback.
122)  */
123) void Pong::newOpConn(const std::string &name, OpConn *pConn)
124) {
125)   // left player joins if none there yet
126)   if (name == m_name + OpConnSuffixLeft && ! m_pConnLeft) {
127)     m_pConnLeft = pConn;
128)     redraw(); // player color is different for phone / computer
129)     return;
130)   }
131)   // right player joins if none there yet
132)   if (name == m_name + OpConnSuffixRight && ! m_pConnRight) {
133)     m_pConnRight = pConn;
134)     redraw(); // player color is different for phone / computer
135)     return;
136)   }
137) }
138) 
139) /**
140)  * @brief key command received on operator connection
141)  * @param[in] pConn operator connection object
142)  * @param[in] key key that was pressed
143)  */
144) void Pong::opConnRecvKey(OpConn *pConn, char key)
145) {
146)   // left player
147)   if (pConn == m_pConnLeft) {
148)     processKey(key, m_leftPosY);
149)     return;
150)   }
151)   // right player
152)   if (pConn == m_pConnRight) {
153)     processKey(key, m_rightPosY);
154)     return;
155)   }
156) }
157) 
158) /**
159)  * @brief play command received on operator connection
160)  * @param[in] pConn operator connection object
161)  * @param[in] sound name of sound to play
162)  */
163) void Pong::opConnRecvPlay(OpConn *pConn, const std::string &sound)
164) {
165)   (void)pConn;
166)   (void)sound;
167) }
168) 
169) /**
170)  * @brief operator connection is closed
171)  * @param[in] pConn operator connection object
172)  *
173)  * The connection may not be used for sending any more in this callback.
174)  */
175) void Pong::opConnClose(OpConn *pConn)
176) {
177)   // left player leaves
178)   if (pConn == m_pConnLeft) {
179)     m_pConnLeft = NULL;
180)     redraw(); // player color is different for phone / computer
181)     return;
182)   }
183)   // right player leaves
184)   if (pConn == m_pConnRight) {
185)     m_pConnRight = NULL;
186)     redraw(); // player color is different for phone / computer
187)     return;
188)   }
189) }
190) 
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

194)   // compute parameters
195)   m_padSize = (m_height + 1) / 3;
196)   m_leftPosY = (m_height - m_padSize) / 2;
197)   m_rightPosY = (m_height - m_padSize) / 2;
Stefan Schuermans pong: make computer slow

Stefan Schuermans authored 5 years ago

198)   m_leftDelay = 0;
199)   m_rightDelay = 0;
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

200) 
201)   // convert colors
202)   color2data(m_fileBallColor, m_ballColor);
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

206) 
207)   // FIXME: start ball for development
208)   startBall();
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

209) }
210) 
211) /// redraw current game image, expected to call sendFrame() at end
212) void Pong::redraw()
213) {
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

214)   int y, x;
215) 
216)   // draw background
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

219)   // draw middle line: single line on odd width, two dashed lines at even width
220)   for (y = 0; y < m_height; ++y) {
221)     x = (m_width - (y & 1)) / 2;
222)     pixel(y, x, m_lineColor);
223)   }
224) 
Stefan Schuermans pong: add pads

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

226)   lineVert(m_leftPosY, m_leftPosY + m_padSize - 1, 0,
227)            m_pConnLeft ? m_padColor : m_computerColor);
228)   lineVert(m_rightPosY, m_rightPosY + m_padSize - 1, m_width - 1,
229)            m_pConnRight ? m_padColor : m_computerColor);
Stefan Schuermans pong: add pads

Stefan Schuermans authored 5 years ago

230) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

235) 
236)   // send updated image buffer as frame
237)   sendFrame();
238) }
239) 
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

240) /// callback when requested time reached
241) void Pong::timeCall()
242) {
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

243)   // game is running
244)   if (m_goalDelay <= 0 && m_ballPosX >= 0 && m_ballPosY >= 0) {
245) 
246)     // computer player: move pads
247)     if (! m_pConnLeft) {
248)       computerLeft();
249)     }
250)     if (! m_pConnRight) {
251)       computerRight();
252)     }
253) 
254)     // bounce ball
255)     bounceBall();
256) 
257)     // move ball
258)     m_ballPosX += m_ballDirX;
259)     m_ballPosY += m_ballDirY;
260) 
261)     // detect goal
262)     detectGoal();
263) 
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

267) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

269) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

270)     // new ball when delay is over
271)     if (m_goalDelay <= 0) {
272)         startBall();
273)         return; // startBall calls redraw() and planTimeCall()
274)     }
275) 
276)   }
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

277) 
278)   // draw and send frame
279)   redraw();
280) 
281)   // request next call if needed
282)   planTimeCall();
283) }
284) 
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

285) /**
286)  * @brief process key received from phone player
287)  * @param[in] key received key from player
288)  * @param[in,out] padPosY y position of player's pad
289)  */
290) void Pong::processKey(char key, int &padPosY)
291) {
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

292)   // do not move pad if goal delay is active
293)   if (m_goalDelay > 0) {
294)     return;
295)   }
296) 
Stefan Schuermans pong: implement phone players

Stefan Schuermans authored 5 years ago

297)   // move pad (2 = up, 8 = down), do not move pad out of field
298)   if (key == '2' && padPosY > 0) {
299)     --padPosY;
300)     redraw();
301)   }
302)   else if (key == '8' && padPosY < m_height - m_padSize) {
303)     ++padPosY;
304)     redraw();
305)   }
306) }
307) 
Stefan Schuermans pong: make computer slow

Stefan Schuermans authored 5 years ago

308) /**
309)  * @brief delay processing for computer players
310)  * @param[in,out] delay delay variable of computer player
311)  * @return whether computer player is allowed to move
312)  */
313) bool Pong::computerDelay(int &delay) const
314) 
315) {
316)   // zero delay: generate new delay
317)   if (delay <= 0) {
318)     int avg_steps = (m_height - m_padSize) / 2;
319)     int delay_range = avg_steps > 1 ? m_width / avg_steps: m_width;
320)     delay = rand() % delay_range + delay_range;
321)   }
322) 
323)   // count down delay
324)   --delay;
325) 
326)   // moving allowd if delay expired
327)   return delay <= 0;
328) }
329) 
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

330) /**
331)  * @brief computation of ideal pad position for computer players
332)  * @param[in] padBallX x coordinate of position of ball when hitting the pad
333)  * @param[in] padY current y coordinate of pad
334)  * @param[out] padYmin minimum ideal y position of pad
335)  * @param[out] padYmax maximum ideal y position of pad
336)  */
337) void Pong::computerComputePadPos(int padBallX, int padY,
338)                                  int &padYmin, int &padYmax) const
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

339) {
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

340)   // ball not moving towards pad
341)   if ((padBallX - m_ballPosX) * m_ballDirX <= 0) {
342)     // do not move if ball is still close to pad
343)     if (abs(padBallX - m_ballPosX) <= 2) {
344)       padYmin = padY;
345)       padYmax = padY;
346)       return;
347)     }
348)     // move pad to middle (might be 2 pixels wide)
349)     padYmin = (m_height - m_padSize) / 2;
350)     padYmax = (m_height - m_padSize + 1) / 2;
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

351)     return;
352)   }
353) 
354)   // compute expected ball position at pad
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

355)   int ballPosX = m_ballPosX; // simulate were ball is going
356)   int ballPosY = m_ballPosY;
357)   int ballDirY = m_ballDirY;
358)   while ((padBallX - ballPosX) * m_ballDirX > 0) { // while moving to pad
359)     int deltaX = padBallX - ballPosX;
360)     int deltaY = deltaX * m_ballDirX * ballDirY;
361)     if (deltaY < -ballPosY) {
362)       deltaY = -ballPosY;
363)       ballPosX += deltaY * m_ballDirX * ballDirY;
364)       ballPosY = 0;
365)       ballDirY = 1;
366)     }
367)     else if (deltaY > m_height - 1 - ballPosY) {
368)       deltaY = m_height - 1 - ballPosY;
369)       ballPosX += deltaY * m_ballDirX * ballDirY;
370)       ballPosY = m_height - 1;
371)       ballDirY = -1;
372)     } else {
373)       ballPosX += deltaX;
374)       ballPosY += deltaY;
375)     }
376)   }
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

379)   padYmin = ballPosY - m_padSize / 2;
380)   padYmax = ballPosY - (m_padSize - 1) / 2;
381) }
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

382) 
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

383) /**
384)  * @brief move pad for computer players
385)  * @param[in] padYmin minimum desired y position of pad
386)  * @param[in] padYmax maximum desired y position of pad
387)  * @param[in,out] padPosY y position of pad
388)  */
389) void Pong::computerMovePad(int padYmin, int padYmax, int &padPosY) const
390) {
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

391)   // do not move pad if goal delay is active
392)   if (m_goalDelay > 0) {
393)     return;
394)   }
395) 
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

396)   // move pad, do not move pad out of field
397)   if (padPosY > padYmax && padPosY > 0) {
398)     --padPosY;
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)   else if (padPosY < padYmin && padPosY < m_height - m_padSize) {
401)     ++padPosY;
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

402)   }
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

404) 
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

405) /// computer player for left pad
406) void Pong::computerLeft()
407) {
Stefan Schuermans pong: make computer slow

Stefan Schuermans authored 5 years ago

408)   if (computerDelay(m_leftDelay)) {
409)     int padYmin, padYmax;
410)     computerComputePadPos(1, m_leftPosY, padYmin, padYmax);
411)     computerMovePad(padYmin, padYmax, m_leftPosY);
412)   }
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

413) }
414) 
415) /// computer player for right pad
416) void Pong::computerRight()
417) {
Stefan Schuermans pong: make computer slow

Stefan Schuermans authored 5 years ago

418)   if (computerDelay(m_rightDelay)) {
419)     int padYmin, padYmax;
420)     computerComputePadPos(m_width - 2, m_rightPosY, padYmin, padYmax);
421)     computerMovePad(padYmin, padYmax, m_rightPosY);
422)   }
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

423) }
424) 
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

425) /// bounce ball
426) void Pong::bounceBall()
427) {
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

429)   bounceBallLeft();
430)   bounceBallRight();
Stefan Schuermans pong: make computer perfect

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

432) }
433) 
434) /// bounce ball at sides
435) void Pong::bounceBallSide()
436) {
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

437)   if (m_ballPosY <= 0 && m_ballDirY < 0) {
438)     m_ballDirY = 1;
439)   }
440)   if (m_ballPosY >= m_height - 1 && m_ballDirY > 0) {
441)     m_ballDirY = -1;
442)   }
443)   if (m_ballPosX <= 0 && m_ballDirX < 0) {
444)     m_ballDirX = 1;
445)   }
446)   if (m_ballPosX >= m_width - 1 && m_ballDirX > 0) {
447)     m_ballDirX = -1;
448)   }
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

449) }
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

451) /// bounce ball at left pad
452) void Pong::bounceBallLeft()
453) {
454)   if (m_ballPosX != 1 || m_ballDirX >= 0) {
455)     return;
Stefan Schuermans pong: add pads

Stefan Schuermans authored 5 years ago

456)   }
457) 
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

458)   // top corner
459)   if (m_ballPosY == m_leftPosY - 1 && m_ballDirY > 0) {
460)     m_ballDirX = 1;
461)     m_ballDirY = -1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

465)   // bottom corner
466)   else if (m_ballPosY == m_leftPosY + m_padSize && m_ballDirY < 0) {
467)     m_ballDirX = 1;
468)     m_ballDirY = 1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

470)   }
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

472)   // pad edge
473)   else if (m_ballPosY >= m_leftPosY &&
474)            m_ballPosY < m_leftPosY + m_padSize) {
475)     m_ballDirX = 1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

477)   }
478) }
479) 
480) /// bounce ball at right pad
481) void Pong::bounceBallRight()
482) {
483)   if (m_ballPosX != m_width - 2 || m_ballDirX <= 0) {
484)     return;
485)   }
486) 
487)   // top corner
488)   if (m_ballPosY == m_rightPosY - 1 && m_ballDirY > 0) {
489)     m_ballDirX = -1;
490)     m_ballDirY = -1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

492)   }
493) 
494)   // bottom corner
495)   else if (m_ballPosY == m_rightPosY + m_padSize && m_ballDirY < 0) {
496)     m_ballDirX = -1;
497)     m_ballDirY = 1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

499)   }
500) 
501)   // pad edge
502)   else if (m_ballPosY >= m_rightPosY &&
503)            m_ballPosY < m_rightPosY + m_padSize) {
504)     m_ballDirX = -1;
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

505)     ++m_bounceCnt;
506)   }
507) }
508) 
509) /// detect goal
510) void Pong::detectGoal()
511) {
512)   static int goalBlinkCnt = 3;
513)   static int goalDelay = goalBlinkCnt * 8 + 3;
514) 
515)   // ball at far left - goal for right player
516)   if (m_ballPosX == 0) {
517)     m_goalDelay = goalDelay;
518)     ++m_scoreRight;
519)   }
520) 
521)   // ball at far right - goal for left player
522)   else if (m_ballPosX == m_width - 1) {
523)     m_goalDelay = goalDelay;
524)     ++m_scoreLeft;
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

525)   }
526) }
527) 
528) /// request next time call - or cancel request if not needed
529) void Pong::planTimeCall()
530) {
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

531)   // no time call needed if game is not running
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

532)   if (m_ballPosX < 0 ||  m_ballPosY < 0) {
533)     m_mgrs.m_callMgr.cancelTimeCall(this);
534)     return;
535)   }
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

536) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

537)   // compute interval based on score and bounce count
538)   float speedup = 10 * (m_scoreLeft + m_scoreRight) + m_bounceCnt;
539)   float interval = 0.05f + 0.1f * expf(-0.03f * speedup);
540) 
541)   // request next time call
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

544)   m_mgrs.m_callMgr.requestTimeCall(this, Time::now() + stepTime);
545) }
546) 
547) /// move ball out of the field and halt it
548) void Pong::hideBall()
549) {
550)   m_ballPosX = -1;
551)   m_ballPosY = -1;
552)   m_ballDirX = 0;
553)   m_ballDirY = 0;
554) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

555)   // no delays, ball has not bounced at pad
556)   m_leftDelay = 0;
557)   m_rightDelay = 0;
558)   m_goalDelay = 0;
559)   m_bounceCnt = 0;
560) 
561)   // draw and send frame
562)   redraw();
563) 
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

564)   // update time call request
565)   planTimeCall();
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

566) }
567) 
568) /// start ball
569) void Pong::startBall()
570) {
571)   // ball starts horizontally at middle of field, vertically random
572)   m_ballPosX = (m_width - (rand() & 1)) / 2;
573)   m_ballPosY = rand() % m_height;
574)   // random diagonal direction
575)   m_ballDirX = (rand() & 1) * 2 - 1;
576)   m_ballDirY = (rand() & 1) * 2 - 1;
577) 
Stefan Schuermans pong: goals, score, speedup

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

589) }
590)