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