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