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