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