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