]> Shamusworld >> Repos - warehouse-man-deluxe/blob - src/gamewidget.cpp
037a26f71471a76d8462354801fa83c53acb6916
[warehouse-man-deluxe] / src / gamewidget.cpp
1 //
2 // gamewidget.cpp: Main game window widget
3 //
4 // by James Hammons
5 // (C) 2013 Underground Software
6 //
7 // JLH = James Hammons <jlhamm@acm.org>
8 //
9 // Who  When        What
10 // ---  ----------  ------------------------------------------------------------
11 // JLH  03/01/2014  Created this file
12 //
13
14 #include "gamewidget.h"
15 #include <unistd.h>                     // for usleep()
16 #include "gameboard.h"
17
18
19 GameWidget::GameWidget(QWidget * parent/*= 0*/): QWidget(parent),
20         level(1), gameBoard(new GameBoard(level)),
21         animating(false), boxMoving(false)
22 //      score(new QLabel)
23 {
24         CreateBackground();
25 //      score->setTextFormat(Qt::PlainText);
26 }
27
28
29 GameWidget::~GameWidget(void)
30 {
31 }
32
33
34 void GameWidget::paintEvent(QPaintEvent * /*event*/)
35 {
36         QPainter painter(this);
37         QFont font;
38
39         font.setPixelSize(titleBox.height() - 8);
40         painter.setFont(font);
41         painter.setPen(QPen(Qt::black, 1.0, Qt::SolidLine));
42         painter.drawText(titleBox, Qt::AlignCenter, gameBoard->name);
43
44         painter.translate(QPoint(offsetX, offsetY));
45         int ptr = 0;
46
47         for(int y=0; y<gameBoard->height; y++)
48         {
49                 for(int x=0; x<gameBoard->width; x++)
50                 {
51                         int tile = gameBoard->board[ptr++];
52                         painter.setPen(QPen(Qt::black, 2.0, Qt::SolidLine));
53                         painter.setBrush(QBrush(Qt::black));
54                         int tileType = tile & (~GTBoxSpot);
55
56                         if (tileType == GTWall)
57                         {
58                                 painter.setBrush(QBrush(Qt::white));
59                                 painter.drawRect(x * maxLength, y * maxLength, maxLength, maxLength);
60                         }
61                         else if ((tileType == GTBox)
62                                 && (!(boxMoving && (movingBoxPositionX == x) && (movingBoxPositionY == y))))
63                         {
64                                 painter.setBrush(QBrush(tile & GTBoxSpot ? Qt::green : Qt::red));
65                                 painter.drawRect(x * maxLength, y * maxLength, maxLength, maxLength);
66                         }
67                         else if ((tileType == GTSpace)
68                                 || ((tileType == GTBox) && (boxMoving && (movingBoxPositionX == x) && (movingBoxPositionY == y))))
69                         {
70                                 painter.setBrush(QBrush(QPixmap(":/bg_marble_g.bmp")));
71                                 painter.drawRect(x * maxLength, y * maxLength, maxLength, maxLength);
72
73                                 if (tile & GTBoxSpot)
74                                 {
75                                         painter.setBrush(QBrush(Qt::magenta));
76 //                              painter.drawRect((x * maxLength) + 20, (y * maxLength) + 20, maxLength - 40, maxLength - 40);
77                                         painter.drawRect((x * maxLength) + (int)(20.0/60.0*(float)maxLength), (y * maxLength) + (int)(20.0/60.0*(float)maxLength), maxLength - (int)(40.0/60.0*(float)maxLength), maxLength - (int)(40.0/60.0*(float)maxLength));
78                                 }
79                         }
80
81                         if ((gameBoard->playerX == x) && (gameBoard->playerY == y) && !animating)
82                         {
83                                 painter.setBrush(QBrush(Qt::yellow));
84 //                              painter.drawEllipse((x * maxLength) + 10, (y * maxLength) + 10, maxLength - 20, maxLength - 20);
85                                 painter.drawEllipse((x * maxLength) + (int)(10.0/60.0*(float)maxLength), (y * maxLength) + (int)(10.0/60.0*(float)maxLength), maxLength - (int)(20.0/60.0*(float)maxLength), maxLength - (int)(20.0/60.0*(float)maxLength));
86                         }
87                 }
88
89                 if (animating)
90                 {
91                         painter.setBrush(QBrush(Qt::yellow));
92 //                      painter.drawEllipse(playerX + 10, playerY + 10, maxLength - 20, maxLength - 20);
93                         painter.drawEllipse(playerX + (int)(10.0/60.0*(float)maxLength), playerY + (int)(10.0/60.0*(float)maxLength), maxLength - (int)(20.0/60.0*(float)maxLength), maxLength - (int)(20.0/60.0*(float)maxLength));
94                 }
95
96                 if (boxMoving)
97                 {
98                         painter.setBrush(QBrush(Qt::red));
99                         painter.drawRect(boxX, boxY, maxLength, maxLength);
100                 }
101         }
102 }
103
104
105 void GameWidget::mousePressEvent(QMouseEvent * event)
106 {
107         if (event->button() == Qt::LeftButton)
108         {
109                 event->accept();
110         }
111 }
112
113
114 void GameWidget::mouseMoveEvent(QMouseEvent * event)
115 {
116         if (event->buttons() & Qt::LeftButton)
117         {
118                 event->accept();
119         }
120 }
121
122
123 void GameWidget::mouseReleaseEvent(QMouseEvent * event)
124 {
125         if (event->button() == Qt::LeftButton)
126         {
127                 event->accept();
128         }
129 }
130
131
132 void GameWidget::mouseDoubleClickEvent(QMouseEvent * event)
133 {
134         if (event->button() == Qt::LeftButton)
135         {
136                 event->accept();
137         }
138 }
139
140
141 void GameWidget::keyPressEvent(QKeyEvent * event)
142 {
143         int key = event->key();
144         float deltaX = 0, deltaY = 0;
145         float px = (float)(gameBoard->playerX * maxLength);
146         float py = (float)(gameBoard->playerY * maxLength);
147         float bx = px, by = py;
148
149         if (key == Qt::Key_Up)
150         {
151                 boxMoving = gameBoard->IsBoxNOfPlayer();
152                 int moveType = gameBoard->MovePlayerN();
153
154                 if (moveType == PMInvalid)
155                         return;
156
157                 deltaY = -1.0;
158         }
159         else if (key == Qt::Key_Down)
160         {
161                 boxMoving = gameBoard->IsBoxSOfPlayer();
162
163                 if (gameBoard->MovePlayerS() == PMInvalid)
164                         return;
165
166                 deltaY = +1.0;
167         }
168         else if (key == Qt::Key_Left)
169         {
170                 boxMoving = gameBoard->IsBoxWOfPlayer();
171
172                 if (gameBoard->MovePlayerW() == PMInvalid)
173                         return;
174
175                 deltaX = -1.0;
176         }
177         else if (key == Qt::Key_Right)
178         {
179                 boxMoving = gameBoard->IsBoxEOfPlayer();
180
181                 if (gameBoard->MovePlayerE() == PMInvalid)
182                         return;
183
184                 deltaX = +1.0;
185         }
186         else
187                 return;
188
189         animating = true;
190 //      update();
191
192         if (boxMoving)
193         {
194                 movingBoxPositionX = gameBoard->playerX + (int)deltaX;
195                 movingBoxPositionY = gameBoard->playerY + (int)deltaY;
196                 bx += deltaX * (float)maxLength;
197                 by += deltaY * (float)maxLength;
198         }
199
200         int steps = 15;
201         float stepSize = (float)maxLength / (float)steps;
202         deltaX *= stepSize, deltaY *= stepSize;
203
204         for(int i=0; i<steps; i++)
205         {
206                 px += deltaX;
207                 py += deltaY;
208                 playerX = (int)px;
209                 playerY = (int)py;
210                 bx += deltaX;
211                 by += deltaY;
212                 boxX = (int)bx;
213                 boxY = (int)by;
214                 repaint();
215                 Pause(3);
216         }
217
218         animating = boxMoving = false;
219
220         // Only update if a key we recognize has been pressed!
221         update();
222
223         if (gameBoard->GameHasBeenWon())
224                 emit GameWasWon();
225 }
226
227
228 void GameWidget::keyReleaseEvent(QKeyEvent * /*event*/)
229 {
230 }
231
232
233 void GameWidget::resizeEvent(QResizeEvent * /*event*/)
234 {
235 //      QSize s = event->size();
236
237 //printf("Size of window is: %i x %i\n", s.width(), s.height());
238 //printf("Size of game grid is: %i x %i\n", gameBoard->width, gameBoard->height);
239 #if 0
240         // Find the constraints
241         float boxSizeX = s.width() / gameBoard->width;
242         float boxSizeY = s.height() / gameBoard->height;
243
244         maxLength = (int)(boxSizeX > boxSizeY ? boxSizeY : boxSizeX);
245 #else
246         ResizeGrid();
247 #endif
248 }
249
250
251 void GameWidget::CreateBackground(void)
252 {
253 #if 0
254         char BGRes[27][64] = {
255                 ":/res/grfttile.bmp",
256                 ":/res/cloth_6.bmp",
257                 ":/res/bg_tech_3.bmp",
258                 ":/res/bg_tech_2.bmp",
259                 ":/res/bg_tech_1.bmp",
260                 ":/res/bg_weave_3.bmp",
261                 ":/res/bg_weave_2.bmp",
262                 ":/res/bg_clouds_2.bmp",
263                 ":/res/bg_floor_plate.bmp",
264                 ":/res/bg_marble_b.bmp",
265                 ":/res/bg_marble_g.bmp",
266                 ":/res/bg_marble_p.bmp",
267                 ":/res/bg_marble_r.bmp",
268                 ":/res/bg_marble_rb.bmp",
269                 ":/res/bg_money_1.bmp",
270                 ":/res/bg_pinstripe2.bmp",
271                 ":/res/bg_pinstripe7.bmp",
272                 ":/res/bg_raindrops_large.bmp",
273                 ":/res/bg_raindrops_small.bmp",
274                 ":/res/bg_stucco.bmp",
275                 ":/res/bg_wood_w.bmp",
276                 ":/res/bg_wood_b1.bmp",
277                 ":/res/bg_wood_d.bmp",
278                 ":/res/bg_wood_f.bmp",
279                 ":/res/bg_wood_mh.bmp",
280                 ":/res/bg_wood_mv.bmp",
281                 ":/res/bg_wood_ro.bmp"
282         };
283
284         QPalette pal = palette();
285         pal.setBrush(backgroundRole(), QBrush(QPixmap(BGRes[m_nBackground])));
286         setAutoFillBackground(true);
287         setPalette(pal);
288
289         return true; // Ignore errors for now...
290 #else
291 //      QPalette pal = palette();
292 //      pal.setBrush(backgroundRole(), QBrush(QPixmap(":/bg_marble_g.bmp")));
293 //      setAutoFillBackground(true);
294 //      setPalette(pal);
295 #endif
296 }
297
298
299 void GameWidget::NextLevel(void)
300 {
301         level++;
302         delete gameBoard;
303         gameBoard = new GameBoard(level);
304         ResizeGrid();
305         update();
306 }
307
308
309 void GameWidget::ResetLevel(void)
310 {
311         gameBoard->ResetGame();
312         update();
313 }
314
315
316 void GameWidget::UndoLastMove(void)
317 {
318         int dx, dy, type;
319
320         float deltaX = 0, deltaY = 0;
321         float px = (float)(gameBoard->playerX * maxLength);
322         float py = (float)(gameBoard->playerY * maxLength);
323         float bx = px, by = py;
324
325         // Return if nothing to undo
326         if (!gameBoard->UndoLastMove(dx, dy, type))
327                 return;
328
329         deltaX = (float)-dx;
330         deltaY = (float)-dy;
331
332         if (type == PMPush)
333                 boxMoving = true;
334
335         animating = true;
336 //      update();
337
338         if (boxMoving)
339         {
340                 movingBoxPositionX = gameBoard->playerX + dx;
341                 movingBoxPositionY = gameBoard->playerY + dy;
342                 bx += (float)(dx * maxLength);
343                 by += (float)(dy * maxLength);
344         }
345
346         int steps = 15;
347         float stepSize = (float)maxLength / (float)steps;
348         deltaX *= stepSize, deltaY *= stepSize;
349
350         for(int i=0; i<steps; i++)
351         {
352                 px += deltaX;
353                 py += deltaY;
354                 playerX = (int)px;
355                 playerY = (int)py;
356                 bx += deltaX;
357                 by += deltaY;
358                 boxX = (int)bx;
359                 boxY = (int)by;
360                 repaint();
361                 Pause(3);
362         }
363
364         animating = boxMoving = false;
365         update();
366 }
367
368
369 void GameWidget::ResizeGrid(void)
370 {
371         QSize s = size();
372
373         // Set some room for the board title (7.5%)
374         float titleHeight = s.height() * 0.075;
375
376         // Find the constraints
377         float boxSizeX = s.width() / gameBoard->width;
378         float boxSizeY = (s.height() - titleHeight) / gameBoard->height;
379
380         maxLength = (int)(boxSizeX > boxSizeY ? boxSizeY : boxSizeX);
381
382         offsetX = (s.width() - (maxLength * gameBoard->width)) / 2;
383         offsetY = ((s.height() - titleHeight) - (maxLength * gameBoard->height)) / 2;
384         titleBox.setRect(0, offsetY, s.width(), titleHeight);
385         offsetY += titleHeight; // Add in the title's height
386 }
387
388
389 //
390 // Halt processing for 'count' milliseconds
391 //
392 void GameWidget::Pause(int count)
393 {
394 //      DWORD endCount = GetTickCount() + count;
395 //      while (GetTickCount() < endCount) {}     // Still crude, but better control
396 #if 1
397         usleep(count * 1000);
398 #else
399         // This causes it to lock up randomly. :-/
400         QTime time;
401         time.start();
402
403         while (time.msec() < count)
404                 ; // Do nothing...
405 #endif
406 }
407