* Use some more constants instead of literals.
[matthijs/ABM2.git] / ABM2 / Playground.cpp
1 #include "Playground.h"\r
2 \r
3 #include "Engine/engine.h"\r
4 #include "Engine/VideoUpdate.h"\r
5 #include "SchemeReader.h"\r
6 \r
7 #if WIN32\r
8 LPD3DXSPRITE d3dspt;\r
9 LPD3DXFONT font;\r
10 \r
11 #endif\r
12 \r
13 Playground::Playground(CKernel* kernel) : ITask(kernel) { }\r
14 \r
15 bool Playground::Start()\r
16 {\r
17         #if WIN32\r
18         background = NULL;\r
19         foreground = NULL;\r
20         font = NULL;\r
21         HRESULT res;\r
22 \r
23         D3DXCreateSprite(d3ddev, &d3dspt);    // create the Direct3D Sprite object\r
24         res = D3DXCreateFont(d3ddev, 15, 10, 0, 1, false, 0, OUT_TT_ONLY_PRECIS, 0, 0, L"times new roman", &font);\r
25         if (res != S_OK)\r
26         {\r
27                 switch (res)\r
28                 {\r
29                         case D3DERR_INVALIDCALL:\r
30                                 foreground = NULL;\r
31                                 break;\r
32                         case D3DXERR_INVALIDDATA:\r
33                                 foreground = NULL;\r
34                                 break;\r
35                         case E_OUTOFMEMORY:\r
36                                 foreground = NULL;\r
37                                 break;\r
38                         default:\r
39                                 foreground = NULL;\r
40                 }\r
41         }\r
42 \r
43         res = D3DXCreateTextureFromFile(d3ddev, L"data/field0.png", &background);\r
44         //res = D3DXCreateTextureFromFile(d3ddev, L"data/tiles0.png", &foreground);\r
45         res = D3DXCreateTextureFromFileEx(d3ddev, L"data/tiles0.png", D3DX_DEFAULT, D3DX_DEFAULT, 1, 0, D3DFMT_UNKNOWN,\r
46                 D3DPOOL_DEFAULT ,D3DX_DEFAULT, D3DX_DEFAULT, D3DCOLOR_ARGB(0, 248, 0, 248), NULL, NULL, &foreground);\r
47         if (res != D3D_OK)\r
48         {\r
49                 switch (res)\r
50                 {\r
51                         case D3DERR_NOTAVAILABLE:\r
52                                 foreground = NULL;\r
53                                 break;\r
54                         case D3DERR_OUTOFVIDEOMEMORY:\r
55                                 foreground = NULL;\r
56                                 break;\r
57                         case D3DERR_INVALIDCALL:\r
58                                 foreground = NULL;\r
59                                 break;\r
60                         case D3DXERR_INVALIDDATA:\r
61                                 foreground = NULL;\r
62                                 break;\r
63                         case E_OUTOFMEMORY:\r
64                                 foreground = NULL;\r
65                                 break;\r
66                         default:\r
67                                 foreground = NULL;\r
68                 }\r
69         }\r
70 \r
71         #endif\r
72         // init playing field\r
73         SchemeReader *scheme = new SchemeReader("Data/schemes/BASIC.SCH");\r
74         for (int i=0; i<PLAYGROUND_COLS; ++i) \r
75         {\r
76                 for (int j=0; j<PLAYGROUND_ROWS; ++j)\r
77                 {\r
78                         field[i][j] = NULL;\r
79                 }\r
80         }\r
81 \r
82         CMMPointer<Sprite> tile_sprite = this->getKernel()->getSpriteManager()->getSprite(SPR_TILE);\r
83         // put in non-destructible blocks\r
84         for (int i=0; i<PLAYGROUND_COLS; i++) \r
85         {\r
86                 for (int j=0; j<PLAYGROUND_ROWS; j++)\r
87                 {\r
88                         int subsprite = -1;\r
89                         switch(scheme->PlayField[j*PLAYGROUND_NUMFIELD_X+i]) {\r
90                                 case BRICK:\r
91                                         subsprite = SPR_SUB_BRICK;\r
92                                         break;\r
93                                 case SOLID:\r
94                                         subsprite = SPR_SUB_SOLID;\r
95                                         break;\r
96                         }\r
97                         if (subsprite != -1)\r
98                                 field[i][j] = new Tile(tile_sprite, subsprite, i, j);\r
99                 }\r
100         }\r
101 /*\r
102         // put in desctructible blocks with chance 90%\r
103         for (int i=0; i<PLAYGROUND_COLS; i+=2) \r
104                 for (int j=0; j<PLAYGROUND_ROWS; ++j)\r
105                         if ((double)rand()/RAND_MAX <= 0.9) field[i][j] = new Tile(foreground, 0, i, j);\r
106         for (int i=1; i<PLAYGROUND_COLS; i+=2) \r
107                 for (int j=0; j<PLAYGROUND_ROWS; j+=2)\r
108                         if ((double)rand()/RAND_MAX <= 0.9) field[i][j] = new Tile(foreground, 0, i, j);\r
109 */      \r
110         // put in a player\r
111         bomberman = new Bomberman(20, 66);\r
112         if (field[0][0] != NULL)\r
113         {\r
114                 delete field[0][0];\r
115                 field[0][0] = NULL;\r
116         }\r
117         if (field[1][0] != NULL)\r
118         {\r
119                 delete field[1][0];\r
120                 field[1][0] = NULL;\r
121         }\r
122         if (field[0][1] != NULL)\r
123         {\r
124                 delete field[0][1];\r
125                 field[0][1] = NULL;\r
126         }\r
127 \r
128         old_counter = GetTickCount();\r
129         return true;\r
130 }\r
131 \r
132 void Playground::Update()\r
133 {\r
134         CMMPointer<Sprite> s = this->getKernel()->getSpriteManager()->getSprite(SPR_FIELD);\r
135         \r
136         s->blit(0, 0, 1.0, 1.0, 0, 0, COLOUR_RGBA(0, 0, 255, 255));\r
137         for (int i=0; i<PLAYGROUND_COLS; ++i) \r
138         {\r
139                 for (int j=0; j<PLAYGROUND_ROWS; ++j)\r
140                 {\r
141                         if (field[i][j] != NULL) field[i][j]->Draw();\r
142                 }\r
143         }\r
144 \r
145         #ifdef WIN32\r
146         bomberman->Update();\r
147         if (CInputTask::keyDown(DIK_RIGHT)) this->move_right();\r
148         if (CInputTask::keyDown(DIK_LEFT)) this->move_left();\r
149         if (CInputTask::keyDown(DIK_UP)) this->move_up();\r
150         if (CInputTask::keyDown(DIK_DOWN)) this->move_down();\r
151 \r
152 \r
153         d3dspt->End();    // end sprite drawing\r
154 \r
155         // do fps thingie\r
156         RECT rect = {10,10,400,36};\r
157         char buf[105];\r
158         DWORD new_counter = GetTickCount();\r
159         DWORD tmp = new_counter-old_counter;\r
160         double tmp2 = 1 / (double(tmp) / 1000.0f);\r
161         /*      if (tmp == 0)\r
162                 _itoa_s(0, buf, 5, 10);\r
163         else\r
164 */\r
165         //_gcvt_s(buf, 105, tmp2, 4);\r
166         sprintf(buf, "%2.2f", tmp2);\r
167         font->DrawTextA(NULL, (char *)&buf, -1, &rect, DT_LEFT, D3DCOLOR_XRGB(255,255,255));\r
168 \r
169         //draw coordinates\r
170         RECT rect2 = {210,10,300,36};\r
171         sprintf(buf, "(%d, %d)", bomberman->getX(), bomberman->getY());\r
172         font->DrawTextA(NULL, (char *)&buf, -1, &rect2, DT_LEFT, D3DCOLOR_XRGB(255,255,255));\r
173 \r
174         //draw bomberman_array position\r
175         RECT rect3 = {310,10,500,36};\r
176         sprintf(buf, "(%d, %d) - (%d,%d)", bomberman->getFieldCenterX(), bomberman->getFieldCenterY(), bomberman->getOffsetX(), bomberman->getOffsetY());\r
177         font->DrawTextA(NULL, (char *)&buf, -1, &rect3, DT_LEFT, D3DCOLOR_XRGB(255,255,255));\r
178         #endif // WIN32\r
179 \r
180         old_counter = GetTickCount();\r
181 }\r
182 \r
183 void Playground::Stop()\r
184 {\r
185         for (int i=0; i<PLAYGROUND_COLS; ++i) \r
186                 for (int j=0; j<PLAYGROUND_ROWS; ++j)\r
187                         if (field[i][j] != NULL) delete field[i][j];\r
188 \r
189         if (bomberman != NULL) delete bomberman;\r
190         #ifdef WIN32\r
191         if (background != NULL) background->Release();\r
192         if (foreground != NULL) foreground->Release();\r
193         if (d3dspt != NULL) d3dspt->Release();\r
194         if (font != NULL) font->Release();\r
195         #endif // WIN32\r
196 }\r
197 \r
198 void Playground::move_down()\r
199 {\r
200         // first check to stay within the playground\r
201         if ((bomberman->getY() + bomberman->getHeight()) < (PLAYGROUND_BORDER_TOP + FIELD_UNIT_HEIGHT * PLAYGROUND_ROWS))\r
202         { // i can go down\r
203                 int array_x = bomberman->getFieldCenterX();\r
204                 int array_left = array_x-1;\r
205                 int array_right = array_x+1;\r
206                 int array_y = bomberman->getFieldCenterY();\r
207                 int array_below = array_y+1;\r
208 \r
209                 if ((array_below <= PLAYGROUND_ROWS) && (field[array_x][array_below] == NULL) &&\r
210                         (bomberman->getOffsetX() == 0))//center of field\r
211                 {\r
212                         //bomberman->move_to(array_x, array_below);\r
213                         bomberman->move_to_direction(S);\r
214                         return;\r
215                 }\r
216                 //special cases for down-left :P\r
217                 if ((field[array_x][array_below] == NULL) && (bomberman->getOffsetX() == 10) && (bomberman->getOffsetY()%2 == 1))\r
218                 {\r
219                         bomberman->move_to_direction(SW);\r
220                         return;\r
221                 }\r
222                 if ((field[array_x][array_below] == NULL) && (bomberman->getOffsetX() == 12) && (bomberman->getOffsetY() == 0))\r
223                 {\r
224                         bomberman->move_to_direction(SW);\r
225                         return;\r
226                 }\r
227 \r
228                 //directly above (according to getCenterX), offset 0-18, down left\r
229                 if ((field[array_x][array_below] == NULL) &&\r
230                         (bomberman->getOffsetX() >= (FIELD_UNIT_HEIGHT/3)))\r
231                 {\r
232                         bomberman->move_to_direction(SWW);\r
233                         return;\r
234                 }\r
235                 if ((field[array_x][array_below] == NULL) &&\r
236                         (bomberman->getOffsetX() < (FIELD_UNIT_HEIGHT/3)))\r
237                 {\r
238                         bomberman->move_to_direction(SSW);\r
239                         return;\r
240                 }\r
241                 //offset 20-36 = down left\r
242                 if ((field[array_left][array_below] == NULL) && (field[array_x][array_below] != NULL) &&\r
243                         (bomberman->getOffsetX() >= (FIELD_UNIT_WIDTH/2)) && (bomberman->getOffsetX() < FIELD_UNIT_WIDTH-2))\r
244                 {\r
245                         bomberman->move_to_direction(SWW);\r
246                         return;\r
247                 }\r
248                 //offset 4-18 = down right\r
249                 if ((field[array_right][array_below] == NULL) && (field[array_x][array_below] != NULL) && \r
250                         (bomberman->getOffsetX() < (FIELD_UNIT_WIDTH/2)) && (bomberman->getOffsetX() > 2))\r
251                 {\r
252                         bomberman->move_to_direction(SEE);\r
253                         return;\r
254                 }\r
255                 //directly above (according to getCenterX), offset 20-38, down right\r
256                 if ((field[array_x][array_below] == NULL) &&\r
257                         (bomberman->getOffsetX() >= (FIELD_UNIT_WIDTH-FIELD_UNIT_HEIGHT/3)))\r
258                 {\r
259                         bomberman->move_to_direction(SEE);\r
260                         return;\r
261                 }\r
262                 if ((field[array_x][array_below] == NULL))\r
263                 {\r
264                         bomberman->move_to_direction(SSE);\r
265                 }\r
266         }\r
267 }\r
268 \r
269 void Playground::move_up()\r
270 {\r
271         // first check to stay within the playground\r
272         if (bomberman->getY() > PLAYGROUND_BORDER_TOP)\r
273         { // i can go up\r
274                 int array_x = bomberman->getFieldCenterX();\r
275                 int array_left = array_x-1;\r
276                 int array_right = array_x+1;\r
277                 int array_y = bomberman->getFieldCenterY();\r
278                 int array_above = array_y-1;\r
279 \r
280                 if ((array_above == -1) || (field[array_x][array_above] == NULL))\r
281                 {\r
282                         bomberman->move_to(array_x, array_above);\r
283                         return;\r
284                 }\r
285                 if ((field[array_left][array_above] == NULL) && (field[array_x][array_above] != NULL) && \r
286                         (bomberman->getCenterX()-PLAYGROUND_BORDER_LEFT < (array_x*40+20)))//linkerkant van midden\r
287                 {\r
288                         bomberman->move_to(array_left, array_above);\r
289                         return;\r
290                 }\r
291                 if ((field[array_right][array_above] == NULL) && (field[array_x][array_above] != NULL) && \r
292                         (bomberman->getCenterX()-PLAYGROUND_BORDER_LEFT > (array_x*40+20)))//rechts van midden\r
293                 {\r
294                         bomberman->move_to(array_right, array_above);\r
295                         return;\r
296                 }\r
297         }\r
298 }\r
299 \r
300 void Playground::move_left()\r
301 {\r
302         // first check to stay within the playground\r
303         if (bomberman->getX() > PLAYGROUND_BORDER_LEFT)\r
304         { // i can go left\r
305                 int array_x = bomberman->getFieldCenterX();\r
306                 int array_left = array_x-1;\r
307                 int array_y = bomberman->getFieldCenterY();\r
308                 int array_below = array_y+1;\r
309                 int array_above = array_y-1;\r
310 \r
311                 if ((array_left == -1) || (field[array_left][array_y] == NULL))\r
312                 {\r
313                         bomberman->move_to(array_left, array_y);\r
314                         return;\r
315                 }\r
316                 if ((field[array_left][array_above] == NULL) && (field[array_left][array_y] != NULL) && \r
317                         (bomberman->getCenterY()-PLAYGROUND_BORDER_TOP < (array_y*36+18)))\r
318                 {\r
319                         bomberman->move_to(array_left, array_above);\r
320                         return;\r
321                 }\r
322                 if ((field[array_left][array_below] == NULL) && (field[array_left][array_y] != NULL) && \r
323                         (bomberman->getCenterY()-PLAYGROUND_BORDER_TOP > (array_y*36+18)))\r
324                 {\r
325                         bomberman->move_to(array_left, array_below);\r
326                         return;\r
327                 }\r
328         }\r
329 }\r
330 \r
331 void Playground::move_right()\r
332 {\r
333         // first check to stay within the playground\r
334         if ((bomberman->getX() + bomberman->getWidth()) < (20 + 40 * PLAYGROUND_COLS))\r
335         { // i can go right\r
336                 int array_x = bomberman->getFieldCenterX();\r
337                 int array_right = array_x+1;\r
338                 int array_y = bomberman->getFieldCenterY();\r
339                 int array_below = array_y+1;\r
340                 int array_above = array_y-1;\r
341 \r
342                 if ((array_right < PLAYGROUND_COLS) && (field[array_right][array_y] == NULL))\r
343                 {\r
344                         bomberman->move_to(array_right, array_y);\r
345                         return;\r
346                 }\r
347                 if ((field[array_right][array_above] == NULL) && (field[array_right][array_y] != NULL) && (bomberman->getCenterY()-PLAYGROUND_BORDER_TOP < (array_y*36+18)))\r
348                 {\r
349                         bomberman->move_to(array_right, array_above);\r
350                         return;\r
351                 }\r
352                 if ((field[array_right][array_below] == NULL) && (field[array_right][array_y] != NULL) && (bomberman->getCenterY()-PLAYGROUND_BORDER_TOP > (array_y*36+18)))\r
353                 {\r
354                         bomberman->move_to(array_right, array_below);\r
355                         return;\r
356                 }\r
357         }\r
358 }\r
359 \r
360 // =============================================\r
361 // Bomberman class\r
362 // =============================================\r
363 \r
364 Bomberman::Bomberman(int xloc, int yloc)\r
365 {\r
366         #ifdef WIN32\r
367         HRESULT res = D3DXCreateTextureFromFile(d3ddev, L"data/powkick.png", &texture);\r
368         if (res != D3D_OK) texture = NULL;\r
369         #endif // WIN32\r
370         x = xloc;\r
371         y = yloc;\r
372 }\r
373 \r
374 Bomberman::~Bomberman()\r
375 {\r
376         #ifdef WIN32\r
377         if (texture != NULL) texture->Release();\r
378         #endif // WIN32\r
379 }\r
380 \r
381 void Bomberman::Update()\r
382 {\r
383         #ifdef WIN32\r
384         D3DXVECTOR3 center(0.0f, 0.0f, 0.0f);    // center at the upper-left corner\r
385         D3DXVECTOR3 position((FLOAT)x, (FLOAT)y, 0.0f);    // position at 50, 50 with no depth\r
386         RECT rect = {0,0,40,36};\r
387         d3dspt->Draw(texture, &rect, &center, &position, D3DCOLOR_XRGB(255,255,255));\r
388         #endif // WIN32\r
389 }\r
390 \r
391 void Bomberman::move(int xloc, int yloc)\r
392 {\r
393         x += xloc;\r
394         y += yloc;\r
395 }\r
396 \r
397 int Bomberman::getY()\r
398 {\r
399         return y;\r
400 }\r
401 \r
402 int Bomberman::getX()\r
403 {\r
404         return x;\r
405 }\r
406 \r
407 int Bomberman::getHeight()\r
408 {\r
409         return 36;\r
410 }\r
411 \r
412 int Bomberman::getWidth()\r
413 {\r
414         return 40;\r
415 }\r
416 \r
417 int Bomberman::getCenterX()\r
418 {\r
419         return (this->getX()+(FIELD_UNIT_WIDTH/2));\r
420 }\r
421 \r
422 int Bomberman::getCenterY()\r
423 {\r
424         return (this->getY()+(FIELD_UNIT_HEIGHT/2));\r
425 }\r
426 \r
427 int Bomberman::getOffsetX()\r
428 {\r
429         return (this->getX()- PLAYGROUND_BORDER_LEFT) % FIELD_UNIT_WIDTH;\r
430 }\r
431 \r
432 int Bomberman::getOffsetY()\r
433 {\r
434         return (this->getY()- PLAYGROUND_BORDER_TOP) % FIELD_UNIT_HEIGHT;\r
435 }\r
436 \r
437 int Bomberman::getFieldCenterX()\r
438 {\r
439         return (this->getCenterX() - PLAYGROUND_BORDER_LEFT)/FIELD_UNIT_WIDTH;\r
440 }\r
441 \r
442 int Bomberman::getFieldCenterY()\r
443 {\r
444         return (this->getCenterY() - PLAYGROUND_BORDER_TOP)/FIELD_UNIT_HEIGHT;\r
445 }\r
446 \r
447 void Bomberman::move_to(int xloc, int yloc)\r
448 {\r
449         /*\r
450         float center_x = (xloc-1)*40+20+20;\r
451         float center_y = (yloc-1)*36+66+18;\r
452         float dist_x = center_x - this->x;\r
453         float dist_y = center_y - this->y;\r
454 \r
455         double dist = sqrt(dist_x*dist_x + dist_y*dist_y);\r
456         */\r
457         int x_move = (xloc*FIELD_UNIT_WIDTH+PLAYGROUND_BORDER_LEFT) - x;\r
458         int y_move = (yloc*FIELD_UNIT_HEIGHT+PLAYGROUND_BORDER_TOP) - y;\r
459 \r
460         if ((x_move == 0) && (y_move > 0)) this->move(0,2);\r
461         if ((x_move == 0) && (y_move < 0)) this->move(0,-2);\r
462         if ((y_move == 0) && (x_move > 0)) this->move(2,0);\r
463         if ((y_move == 0) && (x_move < 0)) this->move(-2,0);\r
464         if ((x_move < 0) && (y_move < 0)) this->move(-1,-1);\r
465         if ((x_move < 0) && (y_move > 0)) this->move(-1,1);\r
466         if ((x_move > 0) && (y_move < 0)) this->move(1,-1);\r
467         if ((x_move > 0) && (y_move > 0)) this->move(1,1);\r
468 }\r
469 \r
470 void Bomberman::move_to_direction(TMoveDirection dir)\r
471 {\r
472         switch(dir)\r
473         {\r
474                 case N: this->move(0,-2); break;\r
475                 case NNE: this->move(1,-2); break;\r
476                 case NE: this->move(1,-1); break;\r
477                 case NEE: this->move(2,-1); break;\r
478                 case E: this->move(2,0); break;\r
479                 case SEE: this->move(2,1); break;\r
480                 case SE: this->move(1,1); break;\r
481                 case SSE: this->move(1,2); break;\r
482                 case S: this->move(0,2); break;\r
483                 case SSW: this->move(-1,2); break;\r
484                 case SW: this->move(-1,1); break;\r
485                 case SWW: this->move(-2,1); break;\r
486                 case W: this->move(-2,0); break;\r
487                 case NWW: this->move(-2,-1); break;\r
488                 case NW: this->move(-1,-1); break;\r
489                 case NNW: this->move(-1,-2); break;\r
490         }\r
491 }\r
492 \r
493 // =============================================\r
494 // Tile class\r
495 // =============================================\r
496 \r
497 Tile::Tile(const CMMPointer<Sprite> &sprite, int subsprite, int col, int row)\r
498 {\r
499         this->sprite = sprite;\r
500         this->col = col;\r
501         this->row = row;\r
502         this->subsprite = subsprite;\r
503 }\r
504 \r
505 Tile::~Tile()\r
506 {\r
507 }\r
508 void Tile::Draw()\r
509 {\r
510         this->sprite->blit(\r
511                 PLAYGROUND_BORDER_LEFT + this->col * FIELD_UNIT_WIDTH,\r
512                 PLAYGROUND_BORDER_TOP + this->row * FIELD_UNIT_HEIGHT,\r
513                 1.0, 1.0, this->subsprite, 0, COLOUR_RGBA(0, 0, 0, 255)\r
514         );\r
515 #ifdef WIN32\r
516         D3DXVECTOR3 center(0.0f, 0.0f, 0.0f);    // center at the upper-left corner\r
517         D3DXVECTOR3 position((FLOAT)PLAYGROUND_BORDER_LEFT+subitem_width*col, (FLOAT)PLAYGROUND_BORDER_TOP+subitem_height*row, 0.0f);    // position at 50, 50 with no depth\r
518         RECT rect = {tex_num*subitem_width,0,(tex_num+1)*subitem_width,subitem_height};\r
519         d3dspt->Draw(texture, &rect, &center, &position, D3DCOLOR_ARGB(255, 255,255,255));\r
520 #endif // WIN32\r
521 }\r
522 \r