ae99ab35fa7bc3678689104ffaaeab8f7722f2b8
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: make ball move

Stefan Schuermans authored 5 years ago

6) #include <stdlib.h>
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

7) #include <string>
8) #include <vector>
9) 
10) #include <BlinkenLib/BlinkenFrame.h>
11) 
12) #include "File.h"
13) #include "Format.h"
14) #include "FormatFile.h"
15) #include "Game.h"
16) #include "Mgrs.h"
17) #include "Module.h"
18) #include "OutStreamFile.h"
19) #include "Pong.h"
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

20) #include "Time.h"
21) #include "TimeCallee.h"
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

22) 
23) namespace Blinker {
24) 
25) /**
26)  * @brief constructor
27)  * @param[in] name module name
28)  * @param[in] mgrs managers
29)  * @param[in] dirBase base directory
30)  */
31) Pong::Pong(const std::string &name, Mgrs &mgrs, const Directory &dirBase):
32)   Game(name, mgrs, dirBase),
33)   m_fileBallColor(dirBase.getFile("ballColor")),
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

35)   m_filePadColor(dirBase.getFile("padColor")),
36)   m_ballColor(), m_lineColor(), m_padColor(),
37)   m_ballPosX(-1), m_ballPosY(-1), m_ballDirX(0), m_ballDirY(0),
38)   m_padSize(0), m_leftPosY(0), m_rightPosY(0)
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

39) {
40)   // FIXME: activate at begin for initial development only
41)   activate();
42) }
43) 
44) /// virtual destructor
45) Pong::~Pong()
46) {
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

49) }
50) 
51) /// check for update of configuration (derived game), return true on update
52) bool Pong::updateConfigGame()
53) {
54)   bool ret = false;
55) 
56)   // color file was modified -> convert color, return true for update
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

58)       colorUpdate(m_fileLineColor, m_lineColor) ||
59)       colorUpdate(m_filePadColor, m_padColor)) {
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

60)     ret = true;
61)   }
62) 
63)   return ret;
64) }
65) 
66) /// re-initialize game (e.g. due to config change)
67) void Pong::reinitialize()
68) {
Stefan Schuermans pong: add pads

Stefan Schuermans authored 5 years ago

69)   // compute parameters
70)   m_padSize = (m_height + 1) / 3;
71)   m_leftPosY = (m_height - m_padSize) / 2;
72)   m_rightPosY = (m_height - m_padSize) / 2;
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

73) 
74)   // convert colors
75)   color2data(m_fileBallColor, m_ballColor);
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

77)   color2data(m_filePadColor, m_padColor);
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

78) 
79)   // FIXME: start ball for development
80)   startBall();
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

81) }
82) 
83) /// redraw current game image, expected to call sendFrame() at end
84) void Pong::redraw()
85) {
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

86)   int y, x;
87) 
88)   // draw background
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

91)   // draw middle line: single line on odd width, two dashed lines at even width
92)   for (y = 0; y < m_height; ++y) {
93)     x = (m_width - (y & 1)) / 2;
94)     pixel(y, x, m_lineColor);
95)   }
96) 
Stefan Schuermans pong: add pads

Stefan Schuermans authored 5 years ago

97)   // draw pads
98)   lineVert(m_leftPosY, m_leftPosY + m_padSize - 1, 0, m_padColor);
99)   lineVert(m_rightPosY, m_rightPosY + m_padSize - 1, m_width - 1, m_padColor);
100) 
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

101)   // draw ball
102)   pixel(m_ballPosY, m_ballPosX, m_ballColor);
Stefan Schuermans begin of Pong game

Stefan Schuermans authored 5 years ago

103) 
104)   // send updated image buffer as frame
105)   sendFrame();
106) }
107) 
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

108) /// callback when requested time reached
109) void Pong::timeCall()
110) {
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

111)   // computer player: move pads
112)   computerLeft();
113)   computerRight();
114) 
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

115)   // bounce ball
116)   bounceBall();
117) 
118)   // move ball
119)   m_ballPosX += m_ballDirX;
120)   m_ballPosY += m_ballDirY;
121) 
122)   // draw and send frame
123)   redraw();
124) 
125)   // request next call if needed
126)   planTimeCall();
127) }
128) 
Stefan Schuermans implement simple, fast comp...

Stefan Schuermans authored 5 years ago

129) /// computer player for left pad
130) void Pong::computerLeft()
131) {
132)   // ball not moving towards pad: do not move
133)   if (m_ballDirX >= 0) {
134)     return;
135)   }
136) 
137)   // compute expected ball position at pad
138)   int expectedY = m_ballPosY + (m_ballPosX - 1) * m_ballDirY;
139) 
140)   // compute pad position to hit ball with center of pad
141)   int padY = expectedY - m_padSize / 2;
142) 
143)   // do not move pad out of field
144)   if (padY < 0) {
145)     padY = 0;
146)   }
147)   if (padY > m_height - m_padSize) {
148)     padY = m_height - m_padSize;
149)   }
150) 
151)   // move pad
152)   if (m_leftPosY < padY) {
153)     ++m_leftPosY;
154)   }
155)   else if (m_leftPosY > padY) {
156)     --m_leftPosY;
157)   }
158) }
159) 
160) /// computer player for right pad
161) void Pong::computerRight()
162) {
163)   // ball not moving towards pad: do not move
164)   if (m_ballDirX <= 0) {
165)     return;
166)   }
167) 
168)   // compute expected ball position at pad
169)   int expectedY = m_ballPosY + (m_width - 2 - m_ballPosX) * m_ballDirY;
170) 
171)   // compute pad position to hit ball with center of pad
172)   int padY = expectedY - m_padSize / 2;
173) 
174)   // do not move pad out of field
175)   if (padY < 0) {
176)     padY = 0;
177)   }
178)   if (padY > m_height - m_padSize) {
179)     padY = m_height - m_padSize;
180)   }
181) 
182)   // move pad
183)   if (m_rightPosY < padY) {
184)     ++m_rightPosY;
185)   }
186)   else if (m_rightPosY > padY) {
187)     --m_rightPosY;
188)   }
189) }
190) 
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

191) /// bounce ball
192) void Pong::bounceBall()
193) {
194)   bounceBallSide();
195)   bounceBallLeft();
196)   bounceBallRight();
197) }
198) 
199) /// bounce ball at sides
200) void Pong::bounceBallSide()
201) {
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

202)   if (m_ballPosY <= 0 && m_ballDirY < 0) {
203)     m_ballDirY = 1;
204)   }
205)   if (m_ballPosY >= m_height - 1 && m_ballDirY > 0) {
206)     m_ballDirY = -1;
207)   }
208)   if (m_ballPosX <= 0 && m_ballDirX < 0) {
209)     m_ballDirX = 1;
210)   }
211)   if (m_ballPosX >= m_width - 1 && m_ballDirX > 0) {
212)     m_ballDirX = -1;
213)   }
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

214) }
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

216) /// bounce ball at left pad
217) void Pong::bounceBallLeft()
218) {
219)   if (m_ballPosX != 1 || m_ballDirX >= 0) {
220)     return;
Stefan Schuermans pong: add pads

Stefan Schuermans authored 5 years ago

221)   }
222) 
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

223)   // top corner
224)   if (m_ballPosY == m_leftPosY - 1 && m_ballDirY > 0) {
225)     m_ballDirX = 1;
226)     m_ballDirY = -1;
Stefan Schuermans pong: add pads

Stefan Schuermans authored 5 years ago

227)   }
228) 
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

229)   // bottom corner
230)   else if (m_ballPosY == m_leftPosY + m_padSize && m_ballDirY < 0) {
231)     m_ballDirX = 1;
232)     m_ballDirY = 1;
233)   }
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

235)   // pad edge
236)   else if (m_ballPosY >= m_leftPosY &&
237)            m_ballPosY < m_leftPosY + m_padSize) {
238)     m_ballDirX = 1;
239)   }
240) }
241) 
242) /// bounce ball at right pad
243) void Pong::bounceBallRight()
244) {
245)   if (m_ballPosX != m_width - 2 || m_ballDirX <= 0) {
246)     return;
247)   }
248) 
249)   // top corner
250)   if (m_ballPosY == m_rightPosY - 1 && m_ballDirY > 0) {
251)     m_ballDirX = -1;
252)     m_ballDirY = -1;
253)   }
254) 
255)   // bottom corner
256)   else if (m_ballPosY == m_rightPosY + m_padSize && m_ballDirY < 0) {
257)     m_ballDirX = -1;
258)     m_ballDirY = 1;
259)   }
260) 
261)   // pad edge
262)   else if (m_ballPosY >= m_rightPosY &&
263)            m_ballPosY < m_rightPosY + m_padSize) {
264)     m_ballDirX = -1;
265)   }
266) }
267) 
268) /// request next time call - or cancel request if not needed
269) void Pong::planTimeCall()
270) {
271)   if (m_ballPosX < 0 ||  m_ballPosY < 0) {
272)     m_mgrs.m_callMgr.cancelTimeCall(this);
273)     return;
274)   }
Stefan Schuermans pong: make ball move

Stefan Schuermans authored 5 years ago

275) 
276)   Time stepTime;
277)   stepTime.fromMs(100);
278)   m_mgrs.m_callMgr.requestTimeCall(this, Time::now() + stepTime);
279) }
280) 
281) /// move ball out of the field and halt it
282) void Pong::hideBall()
283) {
284)   m_ballPosX = -1;
285)   m_ballPosY = -1;
286)   m_ballDirX = 0;
287)   m_ballDirY = 0;
288) 
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

291) }
292) 
293) /// start ball
294) void Pong::startBall()
295) {
296)   // ball starts horizontally at middle of field, vertically random
297)   m_ballPosX = (m_width - (rand() & 1)) / 2;
298)   m_ballPosY = rand() % m_height;
299)   // random diagonal direction
300)   m_ballDirX = (rand() & 1) * 2 - 1;
301)   m_ballDirY = (rand() & 1) * 2 - 1;
302) 
Stefan Schuermans pong: split large time func...

Stefan Schuermans authored 5 years ago

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

Stefan Schuermans authored 5 years ago

305) }
306)