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