* Make the Bomberman draw itself.
[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 Playground::Playground(CKernel* kernel) : ITask(kernel) { }\r
8 \r
9 bool Playground::Start()\r
10 {\r
11         // init playing field\r
12         SchemeReader *scheme = new SchemeReader("Data/schemes/BASIC.SCH");\r
13 \r
14         CMMPointer<Sprite> tile_sprite = this->getKernel()->getSpriteManager()->getSprite(SPR_TILE);\r
15         // put in non-destructible blocks\r
16         for (int col=0; col<PLAYGROUND_COLS; col++) \r
17         {\r
18                 for (int row=0; row<PLAYGROUND_ROWS; row++)\r
19                 {\r
20                         int subsprite = -1;\r
21                         switch(scheme->PlayField[row*PLAYGROUND_NUMFIELD_X+col]) {\r
22                                 case BRICK:\r
23                                         subsprite = SPR_SUB_BRICK;\r
24                                         break;\r
25                                 case SOLID:\r
26                                         subsprite = SPR_SUB_SOLID;\r
27                                         break;\r
28                         }\r
29                         if (subsprite != -1)\r
30                                 field[col][row] = new Tile(tile_sprite, subsprite, col, row);\r
31                         else\r
32                                 field[col][row] = NULL;\r
33                 }\r
34         }\r
35 /*\r
36         // put in desctructible blocks with chance 90%\r
37         for (int i=0; i<PLAYGROUND_COLS; i+=2) \r
38                 for (int j=0; j<PLAYGROUND_ROWS; ++j)\r
39                         if ((double)rand()/RAND_MAX <= 0.9) field[i][j] = new Tile(foreground, 0, i, j);\r
40         for (int i=1; i<PLAYGROUND_COLS; i+=2) \r
41                 for (int j=0; j<PLAYGROUND_ROWS; j+=2)\r
42                         if ((double)rand()/RAND_MAX <= 0.9) field[i][j] = new Tile(foreground, 0, i, j);\r
43 */      \r
44         // put in a player\r
45         CMMPointer<Sprite> player_sprite = this->getKernel()->getSpriteManager()->getSprite(SPR_PLAYER);\r
46         bomberman = new Bomberman(player_sprite, 20, 66);\r
47         if (field[0][0] != NULL)\r
48         {\r
49                 delete field[0][0];\r
50                 field[0][0] = NULL;\r
51         }\r
52         if (field[1][0] != NULL)\r
53         {\r
54                 delete field[1][0];\r
55                 field[1][0] = NULL;\r
56         }\r
57         if (field[0][1] != NULL)\r
58         {\r
59                 delete field[0][1];\r
60                 field[0][1] = NULL;\r
61         }\r
62 \r
63         old_counter = GetTickCount();\r
64         return true;\r
65 }\r
66 \r
67 void Playground::Update()\r
68 {\r
69         CMMPointer<Sprite> s = this->getKernel()->getSpriteManager()->getSprite(SPR_FIELD);\r
70         \r
71         s->blit(0, 0, 1.0, 1.0, 0, 0, COLOUR_RGBA(255, 255, 255, 255));\r
72         for (int i=0; i<PLAYGROUND_COLS; ++i) \r
73         {\r
74                 for (int j=0; j<PLAYGROUND_ROWS; ++j)\r
75                 {\r
76                         if (field[i][j] != NULL) field[i][j]->Draw();\r
77                 }\r
78         }\r
79 \r
80         bomberman->Update();\r
81         if (CInputTask::keyDown(SDLK_RIGHT)) this->move_right();\r
82         if (CInputTask::keyDown(SDLK_LEFT)) this->move_left();\r
83         if (CInputTask::keyDown(SDLK_UP)) this->move_up();\r
84         if (CInputTask::keyDown(SDLK_DOWN)) this->move_down();\r
85 \r
86 \r
87         #ifdef WIN32\r
88         d3dspt->End();    // end sprite drawing\r
89 \r
90         // do fps thingie\r
91         RECT rect = {10,10,400,36};\r
92         char buf[105];\r
93         DWORD new_counter = GetTickCount();\r
94         DWORD tmp = new_counter-old_counter;\r
95         double tmp2 = 1 / (double(tmp) / 1000.0f);\r
96         /*      if (tmp == 0)\r
97                 _itoa_s(0, buf, 5, 10);\r
98         else\r
99 */\r
100         //_gcvt_s(buf, 105, tmp2, 4);\r
101         sprintf(buf, "%2.2f", tmp2);\r
102         font->DrawTextA(NULL, (char *)&buf, -1, &rect, DT_LEFT, D3DCOLOR_XRGB(255,255,255));\r
103 \r
104         //draw coordinates\r
105         RECT rect2 = {210,10,300,36};\r
106         sprintf(buf, "(%d, %d)", bomberman->getX(), bomberman->getY());\r
107         font->DrawTextA(NULL, (char *)&buf, -1, &rect2, DT_LEFT, D3DCOLOR_XRGB(255,255,255));\r
108 \r
109         //draw bomberman_array position\r
110         RECT rect3 = {310,10,500,36};\r
111         sprintf(buf, "(%d, %d) - (%d,%d)", bomberman->getFieldCenterX(), bomberman->getFieldCenterY(), bomberman->getOffsetX(), bomberman->getOffsetY());\r
112         font->DrawTextA(NULL, (char *)&buf, -1, &rect3, DT_LEFT, D3DCOLOR_XRGB(255,255,255));\r
113         #endif // WIN32\r
114 \r
115         old_counter = GetTickCount();\r
116 }\r
117 \r
118 void Playground::Stop()\r
119 {\r
120         for (int i=0; i<PLAYGROUND_COLS; ++i) \r
121                 for (int j=0; j<PLAYGROUND_ROWS; ++j)\r
122                         if (field[i][j] != NULL) delete field[i][j];\r
123 \r
124         if (bomberman != NULL) delete bomberman;\r
125 }\r
126 \r
127 void Playground::move_down()\r
128 {\r
129         // first check to stay within the playground\r
130         if ((bomberman->getY() + bomberman->getHeight()) < (PLAYGROUND_BORDER_TOP + FIELD_UNIT_HEIGHT * PLAYGROUND_ROWS))\r
131         { // i can go down\r
132                 int array_x = bomberman->getFieldCenterX();\r
133                 int array_left = array_x-1;\r
134                 int array_right = array_x+1;\r
135                 int array_y = bomberman->getFieldCenterY();\r
136                 int array_below = array_y+1;\r
137 \r
138                 if ((array_below <= PLAYGROUND_ROWS) && (field[array_x][array_below] == NULL) &&\r
139                         (bomberman->getOffsetX() == 0))//center of field\r
140                 {\r
141                         //bomberman->move_to(array_x, array_below);\r
142                         bomberman->move_to_direction(S);\r
143                         return;\r
144                 }\r
145                 //special cases for down-left :P\r
146                 if ((field[array_x][array_below] == NULL) && (bomberman->getOffsetX() == 10) && (bomberman->getOffsetY()%2 == 1))\r
147                 {\r
148                         bomberman->move_to_direction(SW);\r
149                         return;\r
150                 }\r
151                 if ((field[array_x][array_below] == NULL) && (bomberman->getOffsetX() == 12) && (bomberman->getOffsetY() == 0))\r
152                 {\r
153                         bomberman->move_to_direction(SW);\r
154                         return;\r
155                 }\r
156 \r
157                 //directly above (according to getCenterX), offset 0-18, down left\r
158                 if ((field[array_x][array_below] == NULL) &&\r
159                         (bomberman->getOffsetX() >= (FIELD_UNIT_HEIGHT/3)))\r
160                 {\r
161                         bomberman->move_to_direction(SWW);\r
162                         return;\r
163                 }\r
164                 if ((field[array_x][array_below] == NULL) &&\r
165                         (bomberman->getOffsetX() < (FIELD_UNIT_HEIGHT/3)))\r
166                 {\r
167                         bomberman->move_to_direction(SSW);\r
168                         return;\r
169                 }\r
170                 //offset 20-36 = down left\r
171                 if ((field[array_left][array_below] == NULL) && (field[array_x][array_below] != NULL) &&\r
172                         (bomberman->getOffsetX() >= (FIELD_UNIT_WIDTH/2)) && (bomberman->getOffsetX() < FIELD_UNIT_WIDTH-2))\r
173                 {\r
174                         bomberman->move_to_direction(SWW);\r
175                         return;\r
176                 }\r
177                 //offset 4-18 = down right\r
178                 if ((field[array_right][array_below] == NULL) && (field[array_x][array_below] != NULL) && \r
179                         (bomberman->getOffsetX() < (FIELD_UNIT_WIDTH/2)) && (bomberman->getOffsetX() > 2))\r
180                 {\r
181                         bomberman->move_to_direction(SEE);\r
182                         return;\r
183                 }\r
184                 //directly above (according to getCenterX), offset 20-38, down right\r
185                 if ((field[array_x][array_below] == NULL) &&\r
186                         (bomberman->getOffsetX() >= (FIELD_UNIT_WIDTH-FIELD_UNIT_HEIGHT/3)))\r
187                 {\r
188                         bomberman->move_to_direction(SEE);\r
189                         return;\r
190                 }\r
191                 if ((field[array_x][array_below] == NULL))\r
192                 {\r
193                         bomberman->move_to_direction(SSE);\r
194                 }\r
195         }\r
196 }\r
197 \r
198 void Playground::move_up()\r
199 {\r
200         // first check to stay within the playground\r
201         if (bomberman->getY() > PLAYGROUND_BORDER_TOP)\r
202         { // i can go up\r
203                 int array_x = bomberman->getFieldCenterX();\r
204                 int array_left = array_x-1;\r
205                 int array_right = array_x+1;\r
206                 int array_y = bomberman->getFieldCenterY();\r
207                 int array_above = array_y-1;\r
208 \r
209                 if ((array_above == -1) || (field[array_x][array_above] == NULL))\r
210                 {\r
211                         bomberman->move_to(array_x, array_above);\r
212                         return;\r
213                 }\r
214                 if ((field[array_left][array_above] == NULL) && (field[array_x][array_above] != NULL) && \r
215                         (bomberman->getCenterX()-PLAYGROUND_BORDER_LEFT < (array_x*40+20)))//linkerkant van midden\r
216                 {\r
217                         bomberman->move_to(array_left, array_above);\r
218                         return;\r
219                 }\r
220                 if ((field[array_right][array_above] == NULL) && (field[array_x][array_above] != NULL) && \r
221                         (bomberman->getCenterX()-PLAYGROUND_BORDER_LEFT > (array_x*40+20)))//rechts van midden\r
222                 {\r
223                         bomberman->move_to(array_right, array_above);\r
224                         return;\r
225                 }\r
226         }\r
227 }\r
228 \r
229 void Playground::move_left()\r
230 {\r
231         // first check to stay within the playground\r
232         if (bomberman->getX() > PLAYGROUND_BORDER_LEFT)\r
233         { // i can go left\r
234                 int array_x = bomberman->getFieldCenterX();\r
235                 int array_left = array_x-1;\r
236                 int array_y = bomberman->getFieldCenterY();\r
237                 int array_below = array_y+1;\r
238                 int array_above = array_y-1;\r
239 \r
240                 if ((array_left == -1) || (field[array_left][array_y] == NULL))\r
241                 {\r
242                         bomberman->move_to(array_left, array_y);\r
243                         return;\r
244                 }\r
245                 if ((field[array_left][array_above] == NULL) && (field[array_left][array_y] != NULL) && \r
246                         (bomberman->getCenterY()-PLAYGROUND_BORDER_TOP < (array_y*36+18)))\r
247                 {\r
248                         bomberman->move_to(array_left, array_above);\r
249                         return;\r
250                 }\r
251                 if ((field[array_left][array_below] == NULL) && (field[array_left][array_y] != NULL) && \r
252                         (bomberman->getCenterY()-PLAYGROUND_BORDER_TOP > (array_y*36+18)))\r
253                 {\r
254                         bomberman->move_to(array_left, array_below);\r
255                         return;\r
256                 }\r
257         }\r
258 }\r
259 \r
260 void Playground::move_right()\r
261 {\r
262         // first check to stay within the playground\r
263         if ((bomberman->getX() + bomberman->getWidth()) < (20 + 40 * PLAYGROUND_COLS))\r
264         { // i can go right\r
265                 int array_x = bomberman->getFieldCenterX();\r
266                 int array_right = array_x+1;\r
267                 int array_y = bomberman->getFieldCenterY();\r
268                 int array_below = array_y+1;\r
269                 int array_above = array_y-1;\r
270 \r
271                 if ((array_right < PLAYGROUND_COLS) && (field[array_right][array_y] == NULL))\r
272                 {\r
273                         bomberman->move_to(array_right, array_y);\r
274                         return;\r
275                 }\r
276                 if ((field[array_right][array_above] == NULL) && (field[array_right][array_y] != NULL) && (bomberman->getCenterY()-PLAYGROUND_BORDER_TOP < (array_y*36+18)))\r
277                 {\r
278                         bomberman->move_to(array_right, array_above);\r
279                         return;\r
280                 }\r
281                 if ((field[array_right][array_below] == NULL) && (field[array_right][array_y] != NULL) && (bomberman->getCenterY()-PLAYGROUND_BORDER_TOP > (array_y*36+18)))\r
282                 {\r
283                         bomberman->move_to(array_right, array_below);\r
284                         return;\r
285                 }\r
286         }\r
287 }\r
288 \r
289 // =============================================\r
290 // Bomberman class\r
291 // =============================================\r
292 \r
293 Bomberman::Bomberman(const CMMPointer<Sprite> &sprite, int xloc, int yloc)\r
294 {\r
295         this->sprite = sprite;\r
296         this->x = xloc;\r
297         this->y = yloc;\r
298 }\r
299 \r
300 Bomberman::~Bomberman()\r
301 {\r
302 }\r
303 \r
304 void Bomberman::Update()\r
305 {\r
306         this->sprite->blit(\r
307                 this->x,\r
308                 this->y,\r
309                 1.0, 1.0, 0, 0, COLOUR_RGBA(255, 255, 255, 255)\r
310         );\r
311 }\r
312 \r
313 void Bomberman::move(int xloc, int yloc)\r
314 {\r
315         x += xloc;\r
316         y += yloc;\r
317 }\r
318 \r
319 int Bomberman::getY()\r
320 {\r
321         return y;\r
322 }\r
323 \r
324 int Bomberman::getX()\r
325 {\r
326         return x;\r
327 }\r
328 \r
329 int Bomberman::getHeight()\r
330 {\r
331         return 36;\r
332 }\r
333 \r
334 int Bomberman::getWidth()\r
335 {\r
336         return 40;\r
337 }\r
338 \r
339 int Bomberman::getCenterX()\r
340 {\r
341         return (this->getX()+(FIELD_UNIT_WIDTH/2));\r
342 }\r
343 \r
344 int Bomberman::getCenterY()\r
345 {\r
346         return (this->getY()+(FIELD_UNIT_HEIGHT/2));\r
347 }\r
348 \r
349 int Bomberman::getOffsetX()\r
350 {\r
351         return (this->getX()- PLAYGROUND_BORDER_LEFT) % FIELD_UNIT_WIDTH;\r
352 }\r
353 \r
354 int Bomberman::getOffsetY()\r
355 {\r
356         return (this->getY()- PLAYGROUND_BORDER_TOP) % FIELD_UNIT_HEIGHT;\r
357 }\r
358 \r
359 int Bomberman::getFieldCenterX()\r
360 {\r
361         return (this->getCenterX() - PLAYGROUND_BORDER_LEFT)/FIELD_UNIT_WIDTH;\r
362 }\r
363 \r
364 int Bomberman::getFieldCenterY()\r
365 {\r
366         return (this->getCenterY() - PLAYGROUND_BORDER_TOP)/FIELD_UNIT_HEIGHT;\r
367 }\r
368 \r
369 void Bomberman::move_to(int xloc, int yloc)\r
370 {\r
371         /*\r
372         float center_x = (xloc-1)*40+20+20;\r
373         float center_y = (yloc-1)*36+66+18;\r
374         float dist_x = center_x - this->x;\r
375         float dist_y = center_y - this->y;\r
376 \r
377         double dist = sqrt(dist_x*dist_x + dist_y*dist_y);\r
378         */\r
379         int x_move = (xloc*FIELD_UNIT_WIDTH+PLAYGROUND_BORDER_LEFT) - x;\r
380         int y_move = (yloc*FIELD_UNIT_HEIGHT+PLAYGROUND_BORDER_TOP) - y;\r
381 \r
382         if ((x_move == 0) && (y_move > 0)) this->move(0,2);\r
383         if ((x_move == 0) && (y_move < 0)) this->move(0,-2);\r
384         if ((y_move == 0) && (x_move > 0)) this->move(2,0);\r
385         if ((y_move == 0) && (x_move < 0)) this->move(-2,0);\r
386         if ((x_move < 0) && (y_move < 0)) this->move(-1,-1);\r
387         if ((x_move < 0) && (y_move > 0)) this->move(-1,1);\r
388         if ((x_move > 0) && (y_move < 0)) this->move(1,-1);\r
389         if ((x_move > 0) && (y_move > 0)) this->move(1,1);\r
390 }\r
391 \r
392 void Bomberman::move_to_direction(TMoveDirection dir)\r
393 {\r
394         switch(dir)\r
395         {\r
396                 case N: this->move(0,-2); break;\r
397                 case NNE: this->move(1,-2); break;\r
398                 case NE: this->move(1,-1); break;\r
399                 case NEE: this->move(2,-1); break;\r
400                 case E: this->move(2,0); break;\r
401                 case SEE: this->move(2,1); break;\r
402                 case SE: this->move(1,1); break;\r
403                 case SSE: this->move(1,2); break;\r
404                 case S: this->move(0,2); break;\r
405                 case SSW: this->move(-1,2); break;\r
406                 case SW: this->move(-1,1); break;\r
407                 case SWW: this->move(-2,1); break;\r
408                 case W: this->move(-2,0); break;\r
409                 case NWW: this->move(-2,-1); break;\r
410                 case NW: this->move(-1,-1); break;\r
411                 case NNW: this->move(-1,-2); break;\r
412         }\r
413 }\r
414 \r
415 // =============================================\r
416 // Tile class\r
417 // =============================================\r
418 \r
419 Tile::Tile(const CMMPointer<Sprite> &sprite, int subsprite, int col, int row)\r
420 {\r
421         this->sprite = sprite;\r
422         this->col = col;\r
423         this->row = row;\r
424         this->subsprite = subsprite;\r
425 }\r
426 \r
427 Tile::~Tile()\r
428 {\r
429 }\r
430 void Tile::Draw()\r
431 {\r
432         this->sprite->blit(\r
433                 PLAYGROUND_BORDER_LEFT + this->col * FIELD_UNIT_WIDTH,\r
434                 PLAYGROUND_BORDER_TOP + this->row * FIELD_UNIT_HEIGHT,\r
435                 1.0, 1.0, this->subsprite, 0, COLOUR_RGBA(255, 255, 255, 255)\r
436         );\r
437 }\r
438 \r