pong: display score
Stefan Schuermans

Stefan Schuermans commited on 2019-06-16 10:32:04
Showing 6 changed files, with 142 additions and 1 deletions.

... ...
@@ -3,6 +3,7 @@
3 3
    Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
4 4
    a blinkenarea.org project */
5 5
 
6
+#include <sstream>
6 7
 #include <string>
7 8
 #include <vector>
8 9
 
... ...
@@ -172,6 +173,95 @@ void Game::rectFill(int y1, int y2, int x1, int x2, ColorData const &cd)
172 173
   }
173 174
 }
174 175
 
176
+/**
177
+ * @brief draw a small digit (3x5 pixels) to image buffer
178
+ * @param[in] topY y coordinate of top of digit
179
+ * @param[in] leftX x coordinate of left of digit
180
+ * @param[in] digit to draw ('0'..'9')
181
+ * @param[in] cd color to use for drawing
182
+ */
183
+void Game::digit3x5(int topY, int leftX, char digit, ColorData const &cd)
184
+{
185
+  /**
186
+   * digit data in octal,
187
+   * each row is 3 bits, msb of row is left,
188
+   * msb row is top
189
+   */
190
+  static const unsigned int digitData[10] = {
191
+    075557, 022222, 071747, 071717, 055711,
192
+    074717, 074757, 071111, 075757, 075717
193
+  };
194
+
195
+  if (digit < '0' || digit > '9') {
196
+    return;
197
+  }
198
+  int idx = digit - '0';
199
+  unsigned int data = digitData[idx];
200
+  for (int y = topY; y < topY + 5; ++y) {
201
+    for (int x = leftX; x < leftX + 3; ++x) {
202
+      data <<= 1;
203
+      if (data & 0100000) {
204
+        pixel(y, x, cd);
205
+      }
206
+    }
207
+  }
208
+}
209
+
210
+/**
211
+ * @brief draw small digits (3x5 each, 1 pixel gap) to image buffer
212
+ * @param[in] topY y coordinate of top of digits
213
+ * @param[in] leftX x coordinate of left of digits
214
+ * @param[in] digits to draw (string of '0'..'9')
215
+ * @param[in] cd color to use for drawing
216
+ */
217
+void Game::digits3x5(int topY, int leftX, std::string const &digits,
218
+                     ColorData const &cd)
219
+{
220
+  for (char digit: digits) {
221
+    digit3x5(topY, leftX, digit, cd);
222
+    leftX += 4;
223
+  }
224
+}
225
+
226
+/**
227
+ * @brief draw number using 3x5 digits to image buffer
228
+ * @param[in] anchorY y coordinate of anchor point
229
+ * @param[in] anchorX x coordinate of anchor point
230
+ * @param[in] alignY y alignment, -1 for top, 0 for center, 1 for bottom
231
+ * @param[in] alignX x alignment, -1 for left, 0 for center, 1 for right
232
+ * @param[in] number non-negative number to draw
233
+ * @param[in] cd color to use for drawing
234
+ */
235
+void Game::number3x5(int anchorY, int anchorX, int alignY, int alignX,
236
+                     int number, ColorData const &cd)
237
+{
238
+  // convert number to digits string
239
+  if (number < 0) {
240
+    return;
241
+  }
242
+  std::stringstream digitsStrm;
243
+  digitsStrm << number;
244
+  std::string const &digits = digitsStrm.str();
245
+
246
+  // compute top left position
247
+  int topY, leftX;
248
+  switch (alignY) {
249
+  case -1: topY = anchorY; break;
250
+  case 0: topY = anchorY - 2; break;
251
+  case 1: topY = anchorY - 4; break;
252
+  default: return;
253
+  }
254
+  switch (alignX) {
255
+  case -1: leftX = anchorX; break;
256
+  case 0: leftX = anchorX - 2 * digits.length() + 1; break;
257
+  case 1: leftX = anchorX - 4 * digits.length() + 2; break;
258
+  default: return;
259
+  }
260
+
261
+  // draw digits
262
+  digits3x5(topY, leftX, digits, cd);
263
+}
264
+
175 265
 /// process update of color file, return true on update
176 266
 bool Game::colorUpdate(ColorFile &colorFile, ColorData &data) const
177 267
 {
... ...
@@ -114,6 +114,37 @@ protected:
114 114
   /// draw filled rectangle to image buffer
115 115
   void rectFill(int y1, int y2, int x1, int x2, ColorData const &cd);
116 116
 
117
+  /**
118
+   * @brief draw a small digit (3x5 pixels) to image buffer
119
+   * @param[in] topY y coordinate of top of digit
120
+   * @param[in] leftX x coordinate of left of digit
121
+   * @param[in] digit to draw ('0'..'9')
122
+   * @param[in] cd color to use for drawing
123
+   */
124
+  void digit3x5(int topY, int leftX, char digit, ColorData const &cd);
125
+
126
+  /**
127
+   * @brief draw small digits (3x5 each, 1 pixel gap) to image buffer
128
+   * @param[in] topY y coordinate of top of digits
129
+   * @param[in] leftX x coordinate of left of digits
130
+   * @param[in] digits to draw (string of '0'..'9')
131
+   * @param[in] cd color to use for drawing
132
+   */
133
+  void digits3x5(int topY, int leftX, std::string const &digits,
134
+                 ColorData const &cd);
135
+
136
+  /**
137
+   * @brief draw number using 3x5 digits to image buffer
138
+   * @param[in] anchorY y coordinate of anchor point
139
+   * @param[in] anchorX x coordinate of anchor point
140
+   * @param[in] alignY y alignment, -1 for top, 0 for center, 1 for bottom
141
+   * @param[in] alignX x alignment, -1 for left, 0 for center, 1 for right
142
+   * @param[in] number non-negative number to draw
143
+   * @param[in] cd color to use for drawing
144
+   */
145
+  void number3x5(int anchorY, int anchorX, int alignY, int alignX,
146
+                 int number, ColorData const &cd);
147
+
117 148
   /// process update of color file, return true on update
118 149
   bool colorUpdate(ColorFile &colorFile, ColorData &data) const;
119 150
 
... ...
@@ -43,7 +43,10 @@ Pong::Pong(const std::string &name, Mgrs &mgrs, const Directory &dirBase):
43 43
   m_fileLineColor(dirBase.getFile("lineColor")),
44 44
   m_filePadColor(dirBase.getFile("padColor")),
45 45
   m_fileComputerColor(dirBase.getFile("computerColor")),
46
+  m_fileScoreColor(dirBase.getFile("scoreColor")),
47
+  m_fileGoalColor(dirBase.getFile("goalColor")),
46 48
   m_ballColor(), m_lineColor(), m_padColor(), m_computerColor(),
49
+  m_scoreColor(), m_goalColor(),
47 50
   m_pConnLeft(NULL), m_pConnRight(NULL),
48 51
   m_ballPosX(-1), m_ballPosY(-1), m_ballDirX(0), m_ballDirY(0),
49 52
   m_padSize(0), m_leftPosY(0), m_rightPosY(0), m_leftDelay(0), m_rightDelay(0),
... ...
@@ -84,7 +87,9 @@ bool Pong::updateConfigGame()
84 87
   if (colorUpdate(m_fileBallColor, m_ballColor) ||
85 88
       colorUpdate(m_fileLineColor, m_lineColor) ||
86 89
       colorUpdate(m_filePadColor, m_padColor) ||
87
-      colorUpdate(m_fileComputerColor, m_computerColor)) {
90
+      colorUpdate(m_fileComputerColor, m_computerColor) ||
91
+      colorUpdate(m_fileScoreColor, m_scoreColor) ||
92
+      colorUpdate(m_fileGoalColor, m_goalColor)) {
88 93
     ret = true;
89 94
   }
90 95
 
... ...
@@ -216,6 +221,8 @@ void Pong::reinitialize()
216 221
   color2data(m_fileLineColor, m_lineColor);
217 222
   color2data(m_filePadColor, m_padColor);
218 223
   color2data(m_fileComputerColor, m_computerColor);
224
+  color2data(m_fileScoreColor, m_scoreColor);
225
+  color2data(m_fileGoalColor, m_goalColor);
219 226
 
220 227
   // reset scores
221 228
   m_scoreLeft = 0;
... ...
@@ -239,6 +246,13 @@ void Pong::redraw()
239 246
     pixel(y, x, m_lineColor);
240 247
   }
241 248
 
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
+
242 256
   // draw pads
243 257
   lineVert(m_leftPosY, m_leftPosY + m_padSize - 1, 0,
244 258
            m_pConnLeft ? m_padColor : m_computerColor);
... ...
@@ -172,10 +172,14 @@ protected:
172 172
   ColorFile m_fileLineColor;     ///< color file for center line
173 173
   ColorFile m_filePadColor;      ///< color file for phone player pad
174 174
   ColorFile m_fileComputerColor; ///< color file for computer player pad
175
+  ColorFile m_fileScoreColor;    ///< color file for score when ball is moving
176
+  ColorFile m_fileGoalColor;     ///< color file for score during goal
175 177
   ColorData m_ballColor;         ///< ball color
176 178
   ColorData m_lineColor;         ///< center line color
177 179
   ColorData m_padColor;          ///< phone player pad color
178 180
   ColorData m_computerColor;     ///< computer player pad color
181
+  ColorData m_scoreColor;        ///< score color when ball is moving
182
+  ColorData m_goalColor;         ///< score color during goal
179 183
   OpConn   *m_pConnLeft;         ///< operator connection left player (or NULL)
180 184
   OpConn   *m_pConnRight;        ///< operator connection right player (o NULL)
181 185
   int       m_ballPosX;          ///< ball position X
182 186