pong: implement phone players
Stefan Schuermans

Stefan Schuermans commited on 2019-06-15 20:15:55
Showing 4 changed files, with 216 additions and 9 deletions.

... ...
@@ -15,6 +15,9 @@
15 15
 #include "Game.h"
16 16
 #include "Mgrs.h"
17 17
 #include "Module.h"
18
+#include "OpConn.h"
19
+#include "OpConnIf.h"
20
+#include "OpReqIf.h"
18 21
 #include "OutStreamFile.h"
19 22
 #include "Pong.h"
20 23
 #include "Time.h"
... ...
@@ -22,6 +25,11 @@
22 25
 
23 26
 namespace Blinker {
24 27
 
28
+/// operator connection name suffix for left player's connection
29
+std::string const Pong::OpConnSuffixLeft = "/left";
30
+/// operator connection name suffix for right player's connection
31
+std::string const Pong::OpConnSuffixRight = "/right";
32
+
25 33
 /**
26 34
  * @brief constructor
27 35
  * @param[in] name module name
... ...
@@ -33,10 +41,16 @@ Pong::Pong(const std::string &name, Mgrs &mgrs, const Directory &dirBase):
33 41
   m_fileBallColor(dirBase.getFile("ballColor")),
34 42
   m_fileLineColor(dirBase.getFile("lineColor")),
35 43
   m_filePadColor(dirBase.getFile("padColor")),
36
-  m_ballColor(), m_lineColor(), m_padColor(),
44
+  m_fileComputerColor(dirBase.getFile("computerColor")),
45
+  m_ballColor(), m_lineColor(), m_padColor(), m_computerColor(),
37 46
   m_ballPosX(-1), m_ballPosY(-1), m_ballDirX(0), m_ballDirY(0),
38
-  m_padSize(0), m_leftPosY(0), m_rightPosY(0), m_leftDelay(0), m_rightDelay(0)
47
+  m_padSize(0), m_leftPosY(0), m_rightPosY(0), m_leftDelay(0), m_rightDelay(0),
48
+  m_pConnLeft(NULL), m_pConnRight(NULL)
39 49
 {
50
+  // open operator connection interfaces for left and right player
51
+  m_mgrs.m_opMgr.open(m_name + OpConnSuffixLeft, this);
52
+  m_mgrs.m_opMgr.open(m_name + OpConnSuffixRight, this);
53
+
40 54
   // FIXME: activate at begin for initial development only
41 55
   activate();
42 56
 }
... ...
@@ -44,6 +58,20 @@ Pong::Pong(const std::string &name, Mgrs &mgrs, const Directory &dirBase):
44 58
 /// virtual destructor
45 59
 Pong::~Pong()
46 60
 {
61
+  // close operator connection interfaces
62
+  m_mgrs.m_opMgr.close(m_name + OpConnSuffixLeft);
63
+  m_mgrs.m_opMgr.close(m_name + OpConnSuffixRight);
64
+
65
+  // close open operator connections
66
+  if (m_pConnLeft) {
67
+    m_pConnLeft->close();
68
+    m_pConnLeft = NULL;
69
+  }
70
+  if (m_pConnRight) {
71
+    m_pConnRight->close();
72
+    m_pConnRight = NULL;
73
+  }
74
+
47 75
   // cancel time callback request
48 76
   m_mgrs.m_callMgr.cancelTimeCall(this);
49 77
 }
... ...
@@ -56,13 +84,108 @@ bool Pong::updateConfigGame()
56 84
   // color file was modified -> convert color, return true for update
57 85
   if (colorUpdate(m_fileBallColor, m_ballColor) ||
58 86
       colorUpdate(m_fileLineColor, m_lineColor) ||
59
-      colorUpdate(m_filePadColor, m_padColor)) {
87
+      colorUpdate(m_filePadColor, m_padColor) ||
88
+      colorUpdate(m_fileComputerColor, m_computerColor)) {
60 89
     ret = true;
61 90
   }
62 91
 
63 92
   return ret;
64 93
 }
65 94
 
95
+/**
96
+ * @brief check if accepting new operator connction is possible
97
+ * @param[in] name operator interface name
98
+ * @return if accepting new connection is possible
99
+ */
100
+bool Pong::acceptNewOpConn(const std::string &name)
101
+{
102
+  // left player can join if none there yet
103
+  if (name == m_name + OpConnSuffixLeft && ! m_pConnLeft) {
104
+    return true;
105
+  }
106
+  // right player can join if none there yet
107
+  if (name == m_name + OpConnSuffixRight && ! m_pConnRight) {
108
+    return true;
109
+  }
110
+  // default: reject connection
111
+  return false;
112
+}
113
+
114
+/**
115
+ * @brief new operator connection
116
+ * @param[in] name operator interface name
117
+ * @param[in] pConn operator connection object
118
+ *
119
+ * The new connection may not yet be used for sending inside this callback.
120
+ */
121
+void Pong::newOpConn(const std::string &name, OpConn *pConn)
122
+{
123
+  // left player joins if none there yet
124
+  if (name == m_name + OpConnSuffixLeft && ! m_pConnLeft) {
125
+    m_pConnLeft = pConn;
126
+    redraw(); // player color is different for phone / computer
127
+    return;
128
+  }
129
+  // right player joins if none there yet
130
+  if (name == m_name + OpConnSuffixRight && ! m_pConnRight) {
131
+    m_pConnRight = pConn;
132
+    redraw(); // player color is different for phone / computer
133
+    return;
134
+  }
135
+}
136
+
137
+/**
138
+ * @brief key command received on operator connection
139
+ * @param[in] pConn operator connection object
140
+ * @param[in] key key that was pressed
141
+ */
142
+void Pong::opConnRecvKey(OpConn *pConn, char key)
143
+{
144
+  // left player
145
+  if (pConn == m_pConnLeft) {
146
+    processKey(key, m_leftPosY);
147
+    return;
148
+  }
149
+  // right player
150
+  if (pConn == m_pConnRight) {
151
+    processKey(key, m_rightPosY);
152
+    return;
153
+  }
154
+}
155
+
156
+/**
157
+ * @brief play command received on operator connection
158
+ * @param[in] pConn operator connection object
159
+ * @param[in] sound name of sound to play
160
+ */
161
+void Pong::opConnRecvPlay(OpConn *pConn, const std::string &sound)
162
+{
163
+  (void)pConn;
164
+  (void)sound;
165
+}
166
+
167
+/**
168
+ * @brief operator connection is closed
169
+ * @param[in] pConn operator connection object
170
+ *
171
+ * The connection may not be used for sending any more in this callback.
172
+ */
173
+void Pong::opConnClose(OpConn *pConn)
174
+{
175
+  // left player leaves
176
+  if (pConn == m_pConnLeft) {
177
+    m_pConnLeft = NULL;
178
+    redraw(); // player color is different for phone / computer
179
+    return;
180
+  }
181
+  // right player leaves
182
+  if (pConn == m_pConnRight) {
183
+    m_pConnRight = NULL;
184
+    redraw(); // player color is different for phone / computer
185
+    return;
186
+  }
187
+}
188
+
66 189
 /// re-initialize game (e.g. due to config change)
67 190
 void Pong::reinitialize()
68 191
 {
... ...
@@ -77,6 +200,7 @@ void Pong::reinitialize()
77 200
   color2data(m_fileBallColor, m_ballColor);
78 201
   color2data(m_fileLineColor, m_lineColor);
79 202
   color2data(m_filePadColor, m_padColor);
203
+  color2data(m_fileComputerColor, m_computerColor);
80 204
 
81 205
   // FIXME: start ball for development
82 206
   startBall();
... ...
@@ -97,8 +221,10 @@ void Pong::redraw()
97 221
   }
98 222
 
99 223
   // draw pads
100
-  lineVert(m_leftPosY, m_leftPosY + m_padSize - 1, 0, m_padColor);
101
-  lineVert(m_rightPosY, m_rightPosY + m_padSize - 1, m_width - 1, m_padColor);
224
+  lineVert(m_leftPosY, m_leftPosY + m_padSize - 1, 0,
225
+           m_pConnLeft ? m_padColor : m_computerColor);
226
+  lineVert(m_rightPosY, m_rightPosY + m_padSize - 1, m_width - 1,
227
+           m_pConnRight ? m_padColor : m_computerColor);
102 228
 
103 229
   // draw ball
104 230
   pixel(m_ballPosY, m_ballPosX, m_ballColor);
... ...
@@ -111,8 +237,12 @@ void Pong::redraw()
111 237
 void Pong::timeCall()
112 238
 {
113 239
   // computer player: move pads
240
+  if (! m_pConnLeft) {
114 241
     computerLeft();
242
+  }
243
+  if (! m_pConnRight) {
115 244
     computerRight();
245
+  }
116 246
 
117 247
   // bounce ball
118 248
   bounceBall();
... ...
@@ -128,6 +258,24 @@ void Pong::timeCall()
128 258
   planTimeCall();
129 259
 }
130 260
 
261
+/**
262
+ * @brief process key received from phone player
263
+ * @param[in] key received key from player
264
+ * @param[in,out] padPosY y position of player's pad
265
+ */
266
+void Pong::processKey(char key, int &padPosY)
267
+{
268
+  // move pad (2 = up, 8 = down), do not move pad out of field
269
+  if (key == '2' && padPosY > 0) {
270
+    --padPosY;
271
+    redraw();
272
+  }
273
+  else if (key == '8' && padPosY < m_height - m_padSize) {
274
+    ++padPosY;
275
+    redraw();
276
+  }
277
+}
278
+
131 279
 /**
132 280
  * @brief delay processing for computer players
133 281
  * @param[in,out] delay delay variable of computer player
... ...
@@ -19,6 +19,9 @@
19 19
 #include "Game.h"
20 20
 #include "Mgrs.h"
21 21
 #include "Module.h"
22
+#include "OpConn.h"
23
+#include "OpConnIf.h"
24
+#include "OpReqIf.h"
22 25
 #include "OutStreamFile.h"
23 26
 #include "Time.h"
24 27
 #include "TimeCallee.h"
... ...
@@ -26,7 +29,7 @@
26 29
 namespace Blinker {
27 30
 
28 31
 /// pong game
29
-class Pong: public Game, public TimeCallee
32
+class Pong: public Game, public OpReqIf, public TimeCallee
30 33
 {
31 34
 public:
32 35
   /**
... ...
@@ -51,6 +54,44 @@ public:
51 54
   /// check for update of configuration (derived game), return true on update
52 55
   virtual bool updateConfigGame();
53 56
 
57
+  /**
58
+   * @brief check if accepting new operator connction is possible
59
+   * @param[in] name operator interface name
60
+   * @return if accepting new connection is possible
61
+   */
62
+  virtual bool acceptNewOpConn(const std::string &name);
63
+
64
+  /**
65
+   * @brief new operator connection
66
+   * @param[in] name operator interface name
67
+   * @param[in] pConn operator connection object
68
+   *
69
+   * The new connection may not yet be used for sending inside this callback.
70
+   */
71
+  virtual void newOpConn(const std::string &name, OpConn *pConn);
72
+
73
+  /**
74
+   * @brief key command received on operator connection
75
+   * @param[in] pConn operator connection object
76
+   * @param[in] key key that was pressed
77
+   */
78
+  virtual void opConnRecvKey(OpConn *pConn, char key);
79
+
80
+  /**
81
+   * @brief play command received on operator connection
82
+   * @param[in] pConn operator connection object
83
+   * @param[in] sound name of sound to play
84
+   */
85
+  virtual void opConnRecvPlay(OpConn *pConn, const std::string &sound);
86
+
87
+  /**
88
+   * @brief operator connection is closed
89
+   * @param[in] pConn operator connection object
90
+   *
91
+   * The connection may not be used for sending any more in this callback.
92
+   */
93
+  virtual void opConnClose(OpConn *pConn);
94
+
54 95
 protected:
55 96
   /// re-initialize game (e.g. due to config change)
56 97
   virtual void reinitialize();
... ...
@@ -61,6 +102,13 @@ protected:
61 102
   /// callback when requested time reached
62 103
   virtual void timeCall();
63 104
 
105
+  /**
106
+   * @brief process key received from phone player
107
+   * @param[in] key received key from player
108
+   * @param[in,out] padPosY y position of player's pad
109
+   */
110
+  void processKey(char key, int &padPosY);
111
+
64 112
   /**
65 113
    * @brief delay processing for computer players
66 114
    * @param[in,out] delay delay variable of computer player
... ...
@@ -114,12 +162,20 @@ protected:
114 162
   void startBall();
115 163
 
116 164
 protected:
165
+
166
+  /// operator connection name suffix for left player's connection
167
+  static std::string const OpConnSuffixLeft;
168
+  /// operator connection name suffix for right player's connection
169
+  static std::string const OpConnSuffixRight;
170
+
117 171
   ColorFile m_fileBallColor;     ///< color file for ball color
118 172
   ColorFile m_fileLineColor;     ///< color file for center line
119
-  ColorFile m_filePadColor;  ///< color file for player pad
173
+  ColorFile m_filePadColor;      ///< color file for phone player pad
174
+  ColorFile m_fileComputerColor; ///< color file for computer player pad
120 175
   ColorData m_ballColor;         ///< ball color
121 176
   ColorData m_lineColor;         ///< center line color
122
-  ColorData m_padColor;      ///< player pad color
177
+  ColorData m_padColor;          ///< phone player pad color
178
+  ColorData m_computerColor;     ///< computer player pad color
123 179
   int       m_ballPosX;          ///< ball position X
124 180
   int       m_ballPosY;          ///< ball position Y
125 181
   int       m_ballDirX;          ///< ball direction X
... ...
@@ -129,6 +185,8 @@ protected:
129 185
   int       m_rightPosY;         ///< position of top pixel of right pad
130 186
   int       m_leftDelay;         ///< delay for computer moving left pad
131 187
   int       m_rightDelay;        ///< delay for computer moving right pad
188
+  OpConn   *m_pConnLeft;         ///< operator connection of left player (or NULL)
189
+  OpConn   *m_pConnRight;        ///< operator connection of right player (or NULL)
132 190
 }; // class Canvas
133 191
 
134 192
 } // namespace Blinker
135 193