]> git.mxchange.org Git - quix0rs-blobwars.git/blob - src/map.cpp
Fix new compiler warnings thrown by gcc-4.6
[quix0rs-blobwars.git] / src / map.cpp
1 /*
2 Copyright (C) 2004-2010 Parallel Realities
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20
21 #include "map.h"
22
23 void drawMap()
24 {
25         SDL_Rect r;
26
27         int offsetX = (int)(engine.playerPosX);
28         int offsetY = (int)(engine.playerPosY);
29
30         map.offsetX = offsetX;
31         map.offsetY = offsetY;
32
33         Math::limitInt(&offsetX, 0, ((MAPWIDTH - 40) * BRICKSIZE));
34         Math::limitInt(&offsetY, 0, ((MAPHEIGHT - 30) * BRICKSIZE));
35
36         int mapx = offsetX >> BRICKSHIFT;
37         int mapy = offsetY >> BRICKSHIFT;
38         int brick = 0;
39
40         for (int x = 0 ; x < 21 ; x++)
41         {
42                 for (int y = 0 ; y < 16 ; y++)
43                 {
44                         brick = map.data[mapx + x][mapy + y];
45
46                         r.x = ((x * BRICKSIZE) - (offsetX & (BRICKSIZE - 1)));
47                         r.y = ((y * BRICKSIZE) - (offsetY & (BRICKSIZE - 1)));
48                         r.w = r.h = BRICKSIZE;
49
50                         if ((brick >= MAP_BREAKABLE) && (brick < MAP_WATERANIM))
51                         {
52                                 graphics.blit(graphics.tile[brick], r.x, r.y, graphics.screen, false);
53                                 
54                                 #if DEBUG
55                                 if ((brick >= MAP_NORESET) && (brick < MAP_DECORATION))
56                                 {
57                                         graphics.drawRect(r.x, r.y, 32, 4, graphics.yellow, graphics.screen);
58                                 }
59                                 #endif
60                         }
61                 }
62         }
63 }
64
65 void drawMapTopLayer()
66 {
67         SDL_Rect r;
68
69         int offsetX = map.offsetX;
70         int offsetY = map.offsetY;
71
72         Math::limitInt(&offsetX, 0, ((MAPWIDTH - 40) * BRICKSIZE));
73         Math::limitInt(&offsetY, 0, ((MAPHEIGHT - 30) * BRICKSIZE));
74
75         int mapx = offsetX >> BRICKSHIFT;
76         int mapy = offsetY >> BRICKSHIFT;
77
78         int brick;
79
80         for (int x = 0 ; x < 21 ; x++)
81         {
82                 for (int y = 0 ; y < 16 ; y++)
83                 {
84                         r.x = ((x * BRICKSIZE) - (offsetX & (BRICKSIZE - 1)));
85                         r.y = ((y * BRICKSIZE) - (offsetY & (BRICKSIZE - 1)));
86                         r.w = r.h = BRICKSIZE;
87
88                         brick = map.data[mapx + x][mapy + y];
89
90                         if (brick == 0)
91                         {
92                                 continue;
93                         }
94
95                         if ((brick < MAP_BREAKABLE) || (brick >= MAP_WATERANIM))
96                         {
97                                 if (brick == MAP_WATER)
98                                 {
99                                         if (map.data[mapx + x][mapy + y + 1] >= MAP_BREAKABLE)
100                                         {
101                                                 addBubble((mapx + x) * BRICKSIZE, (mapy + y) * BRICKSIZE);
102                                         }
103                                 }
104
105                                 if (brick == MAP_WATERANIM)
106                                 {
107                                         brick = graphics.getWaterAnim();
108                                 }
109                                 else if (brick == MAP_SLIME)
110                                 {
111                                         brick = graphics.getSlimeAnim();
112                                 }
113                                 else if ((brick >= MAP_LAVAANIM) && (brick < MAP_TOPLAYER))
114                                 {
115                                         map.data[mapx + x][mapy + y] = graphics.getLavaAnim(brick);
116                                         brick = map.data[mapx + x][mapy + y];
117                                 }
118
119                                 graphics.blit(graphics.tile[brick], r.x, r.y, graphics.screen, false);
120                         }
121                 }
122         }
123 }
124
125 void addBlips(List *blipList, int mapX, int mapY, int type)
126 {
127         Sprite *blipType;
128         Entity *ent;
129
130         switch (type)
131         {
132                 case 1:
133                         blipType = graphics.getSprite("MIAArrow", true);
134                         ent = (Entity*)map.miaList.getHead();
135                         break;
136                 case 2:
137                         blipType = graphics.getSprite("ItemArrow", true);
138                         ent = (Entity*)map.itemList.getHead();
139                         break;
140                 case 3:
141                         blipType = graphics.getSprite("EnemyArrow", true);
142                         ent = (Entity*)map.enemyList.getHead();
143                         break;
144                 default:
145                         return;
146         }
147
148         RadarBlip *blip;
149         int x, y;
150
151         while (ent->next != NULL)
152         {
153                 ent = (Entity*)ent->next;
154
155                 if (ent->health <= 0)
156                         continue;
157
158                 if (type == 3)
159                 {
160                         if (!requiredEnemy(ent->name))
161                         {
162                                 continue;
163                         }
164                 }
165
166                 // Items
167                 if (type == 2)
168                 {
169                         if ((ent->id < ITEM_MISC) || (ent->id == ITEM_MISC_INVISIBLE))
170                         {
171                                 continue;
172                         }
173                 }
174
175                 x = (int)(ent->x + ent->width) >> BRICKSHIFT;
176                 y = (int)(ent->y + ent->height) >> BRICKSHIFT;
177
178                 x -= mapX;
179                 y -= mapY;
180
181                 x = (160) + (x * 5);
182                 y = (120) + (y * 5);
183
184                 if ((x >= 165) && (y >= 125) && (x <= 475) && (y <= 355))
185                 {
186                         blip = new RadarBlip();
187                         blip->set(x, y, type);
188                         blipList->add (blip);
189                 }
190                 else
191                 {
192                         if (y < 125)
193                                 graphics.blit(blipType->image[0], 220 + (type * 50), 100, graphics.screen, true);
194                         if (x > 475)
195                                 graphics.blit(blipType->image[1], 510, 140 + (type * 50), graphics.screen, true);
196                         if (y > 355)
197                                 graphics.blit(blipType->image[2], 220 + (type * 50), 380, graphics.screen, true);
198                         if (x < 165)
199                                 graphics.blit(blipType->image[3], 125, 140 + (type * 50), graphics.screen, true);
200                 }
201         }
202 }
203
204 void addMiniMapDoors(SDL_Surface *panel, int mapX, int mapY)
205 {
206         Train *train = (Train*)map.trainList.getHead();
207
208         int x, y;
209         int width, height, color;
210
211         while (train->next != NULL)
212         {
213                 train = (Train*)train->next;
214                 
215                 width = 5;
216                 height = 5;
217                 color = graphics.white;
218                 
219                 x = (int)train->x >> BRICKSHIFT;
220                 
221                 y = (int)train->y >> BRICKSHIFT;
222                 
223                 if ((x >= mapX) && (x <= mapX + 64) && (y >= mapY) && (y <= mapY + 48))
224                 {
225                         x -= mapX;
226                         y -= mapY;
227                         
228                         if (train->type == TR_TRAIN)
229                         {
230                                 width = 10;
231                         }
232                         else if ((train->type >= TR_SLIDEDOOR) && (train->type <= TR_BRONZE_SLIDEDOOR))
233                         {
234                                 width = 10;
235                         }
236                         else
237                         {
238                                 height = 10;
239                         }
240                         
241                         switch (train->type)
242                         {
243                                 case TR_GOLD_DOOR:
244                                 case TR_GOLD_SLIDEDOOR:
245                                         color = graphics.yellow;
246                                         break;
247                                         
248                                 case TR_SILVER_DOOR:
249                                 case TR_SILVER_SLIDEDOOR:
250                                         color = graphics.grey;
251                                         break;
252                                         
253                                 case TR_BRONZE_DOOR:
254                                 case TR_BRONZE_SLIDEDOOR:
255                                         color = SDL_MapRGB(graphics.screen->format, 0xff, 0x99, 0x00);
256                                         break;
257                                         
258                                 case TR_DOOR:
259                                 case TR_LOCKED_DOOR:
260                                 case TR_LOCKED_SLIDEDOOR:
261                                         color = SDL_MapRGB(graphics.screen->format, 0xff, 0x00, 0xff);
262                                         break;
263                         }
264                         
265                         graphics.drawRect(x * 5, y * 5, width, height, color, panel);
266                 }
267         }
268 }
269
270 void showMap(int centerX, int centerY)
271 {
272         char string[100];
273         int x1, y1, x2, y2;
274
275         x1 = centerX - 32;
276         x2 = centerX + 32;
277         y1 = centerY - 24;
278         y2 = centerY + 24;
279         
280         int minX = (map.limitLeft >> BRICKSHIFT);
281         int maxX = (map.limitRight >> BRICKSHIFT) - 44;
282         int minY = (map.limitUp >> BRICKSHIFT);
283         int maxY = (map.limitDown >> BRICKSHIFT) - 33;
284
285         Math::limitInt(&x1, minX, maxX);
286         Math::limitInt(&x2, minX, maxX);
287         Math::limitInt(&y1, minY, maxY);
288         Math::limitInt(&y2, minY, maxY);
289
290         SDL_FillRect(graphics.screen, NULL, graphics.black);
291         graphics.updateScreen();
292         SDL_Delay(500);
293         
294         SDL_Surface *panel = graphics.createSurface(320, 240);
295         SDL_Surface *background = graphics.loadImage("gfx/main/mapBackground.png");
296         SDL_SetAlpha(background, SDL_SRCALPHA|SDL_RLEACCEL, 130);
297         
298         graphics.blit(background, 0, 0, panel, false);
299         
300         int color = graphics.black;
301         
302         for (int y = 0 ; y < 48 ; y++)
303         {
304                 for (int x = 0 ; x < 64 ; x++)
305                 {
306                         if (map.data[x1 + x][y1 + y] == MAP_WATER)
307                         {
308                                 graphics.drawRect(x * 5, y * 5, 5, 5, graphics.blue, panel);
309                         }
310                 }
311         }
312         
313         addMiniMapDoors(panel, x1, y1);
314
315         for (int y = 0 ; y < 48 ; y++)
316         {
317                 for (int x = 0 ; x < 64 ; x++)
318                 {
319                         color = -1;
320
321                         if (map.data[x1 + x][y1 + y] == MAP_AIR)
322                         {
323                                 color = -1;
324                         }
325                         else if (map.data[x1 + x][y1 + y] == MAP_WATER)
326                         {
327                                 color = -1;
328                         }
329                         else if (map.data[x1 + x][y1 + y] == MAP_SLIME)
330                         {
331                                 color = graphics.green;
332                         }
333                         else if (map.data[x1 + x][y1 + y] == MAP_LAVA)
334                         {
335                                 color = graphics.red;
336                         }
337                         else if (map.data[x1 + x][y1 + y] >= MAP_DECORATION)
338                         {
339                                 color = -1;
340                                 
341                                 if (map.data[x1 + x][y1 + y - 1] == MAP_WATER)
342                                 {
343                                         color = graphics.blue;
344                                 }
345                                 else if (map.data[x1 + x][y1 + y + 1] == MAP_WATER)
346                                 {
347                                         color = graphics.blue;
348                                 }
349                         }
350                         else if (map.data[x1 + x][y1 + y] < MAP_WATERANIM)
351                         {
352                                 color = graphics.darkGreen;
353                         }
354
355                         if (color > -1)
356                         {
357                                 graphics.drawRect(x * 5, y * 5, 5, 5, color, panel);
358                         }
359                 }
360         }
361
362         graphics.blit(background, 0, 0, graphics.screen, false);
363         SDL_FreeSurface(background);
364
365         List blipList;
366
367         RadarBlip *blip = new RadarBlip();
368         blip->set(160 + ((centerX - x1) * 5), 120 + ((centerY - y1) * 5), 0);
369         blipList.add(blip);
370
371         addBlips(&blipList, x1, y1, 1);
372         addBlips(&blipList, x1, y1, 2);
373         addBlips(&blipList, x1, y1, 3);
374         
375         Sprite *enemySignal = graphics.getSprite("EnemySignal", true);
376         Sprite *miaSignal = graphics.getSprite("MIASignal", true);
377         Sprite *bobSignal = graphics.getSprite("BobSignal", true);
378         Sprite *itemSignal = graphics.getSprite("ItemSignal", true);
379
380         graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
381         graphics.setFontSize(3);
382         graphics.drawString(_(game.stageName), 320, 30, TXT_CENTERED, graphics.screen);
383
384         graphics.setFontSize(0);
385         
386         graphics.drawRect(160, 414, 7, 7, graphics.yellow, graphics.white, graphics.screen);
387         graphics.drawString(_("MIAs"), 175, 410, TXT_LEFT, graphics.screen);
388
389         graphics.drawRect(290, 414, 7, 7, graphics.blue, graphics.white, graphics.screen);
390         graphics.drawString(_("Items"), 305, 410, TXT_LEFT, graphics.screen);
391
392         graphics.drawRect(415, 414, 7, 7, graphics.red, graphics.white, graphics.screen);
393         graphics.drawString(_("Enemies"), 430, 410, TXT_LEFT, graphics.screen);
394
395         graphics.setFontSize(1);
396         snprintf(string, sizeof string, "%s - %.2d:%.2d:%.2d", _("Mission Time"), game.currentMissionHours, game.currentMissionMinutes, game.currentMissionSeconds);
397         graphics.drawString(string, 320, 60, TXT_CENTERED, graphics.screen);
398         graphics.drawString(_("Press Button to Continue..."), 320, 450, TXT_CENTERED, graphics.screen);
399
400         engine.flushInput();
401         engine.clearInput();
402
403         doMusicInfo(-1);
404
405         while (true)
406         {
407                 engine.getInput();
408                 config.populate();
409                 graphics.updateScreen();
410                 graphics.animateSprites();
411
412                 graphics.drawRect(160, 120, 320, 240, graphics.black, graphics.white, graphics.screen);
413                 graphics.blit(panel, 160, 120, graphics.screen, false);
414
415                 if ((config.isControl(CONTROL::MAP)) || (config.isControl(CONTROL::PAUSE)) || (engine.keyState[SDLK_ESCAPE]))
416                 {
417                         break;
418                 }
419
420                 blip = (RadarBlip*)blipList.getHead();
421
422                 while (blip->next != NULL)
423                 {
424                         blip = (RadarBlip*)blip->next;
425
426                         switch (blip->type)
427                         {
428                                 case 0:
429                                         graphics.blit(bobSignal->getCurrentFrame(), blip->x, blip->y, graphics.screen, true);
430                                         break;
431                                 case 1:
432                                         graphics.blit(miaSignal->getCurrentFrame(), blip->x, blip->y, graphics.screen, true);
433                                         break;
434                                 case 2:
435                                         graphics.blit(itemSignal->getCurrentFrame(), blip->x, blip->y, graphics.screen, true);
436                                         break;
437                                 case 3:
438                                         graphics.blit(enemySignal->getCurrentFrame(), blip->x, blip->y, graphics.screen, true);
439                                         break;
440                         }
441                 }
442
443                 SDL_Delay(16);
444         }
445
446         blipList.clear();
447
448         SDL_FillRect(graphics.screen, NULL, graphics.black);
449         graphics.updateScreen();
450         SDL_Delay(500);
451
452         engine.flushInput();
453         engine.clearInput();
454 }
455
456 void evaluateMapAttribute(Entity *ent, int mapAttribute)
457 {
458         switch (mapAttribute)
459         {
460                 case MAP_AIR_WALL_1:
461                 case MAP_AIR_WALL_2:
462                 case MAP_AIR_WALL_3:
463                 case MAP_AIR_CEILING_1:
464                         mapAttribute = MAP_AIR;
465                         break;
466                 case MAP_AIR_WALL_4:
467                         if (map.isCavesTileset)
468                         {
469                                 mapAttribute = MAP_AIR;
470                         }
471                         break;
472                 case MAP_AIR_CEILING_2:
473                         if (map.isGrasslandsTileset)
474                         {
475                                 mapAttribute = MAP_AIR;
476                         }
477                         else if (map.isCavesTileset)
478                         {
479                                 mapAttribute = MAP_WATER;
480                         }
481                         break;
482                 case MAP_WATER_WALL:
483                         if (map.isCavesTileset)
484                         {
485                                 mapAttribute = MAP_WATER;
486                         }
487                         break;
488         }
489
490         switch (mapAttribute)
491         {
492                 case MAP_AIR:
493                         if ((ent->environment != ENV_AIR) && (!(ent->flags & ENT_INANIMATE)))
494                         {
495                                 if (!(ent->flags & ENT_SWIMS))
496                                 {
497                                         if (ent->dy < 0)
498                                         {
499                                                 ent->dy = PLAYER_JUMP_SPEED;
500                                         }
501
502                                         if (ent == &player)
503                                         {
504                                                 if ((ent == &player) && ((game.hasAquaLung) || (engine.cheatExtras)))
505                                                 {
506                                                         player.setSprites(graphics.getSprite("BobRight", true), graphics.getSprite("BobLeft", true), graphics.getSprite("BobSpin", true));
507                                                 }
508                                         }
509
510                                         ent->environment = ENV_AIR;
511                                         
512                                         if (ent->dy < 0)
513                                         {
514                                                 audio.playSound(SND_WATEROUT, CH_TOUCH);
515                                         }
516
517                                         ent->checkEnvironment();
518                                 }
519                         }
520                         ent->falling = true;
521                 case MAP_SOLID:
522                         break;
523                 case MAP_WATER:
524                 case MAP_SLIME:
525                 case MAP_LAVA:
526
527                         ent->falling = false;
528
529                         if (ent->environment == ENV_AIR)
530                         {
531                                 audio.playSound(SND_WATERIN, CH_TOUCH);
532                                 if ((mapAttribute == MAP_SLIME) || (mapAttribute == MAP_LAVA))
533                                         ent->thinktime = 1;
534                         }
535                         
536                         // On ice levels water is harmful (because it's very very cold!)
537                         if ((map.isIceLevel) && (mapAttribute == MAP_WATER))
538                         {
539                                 mapAttribute = MAP_LAVA;
540                                 ent->thinktime = 1;
541                         }
542
543                         if (mapAttribute == MAP_WATER)
544                         {
545                                 ent->environment = ENV_WATER;
546                                 if ((ent == &player) && ((game.hasAquaLung) || (engine.cheatExtras)))
547                                 {
548                                         player.setSprites(graphics.getSprite("AquaBobRight", true), graphics.getSprite("AquaBobLeft", true), graphics.getSprite("AquaBobSpin", true));
549                                 }
550                         }
551                         else if (mapAttribute == MAP_SLIME)
552                         {
553                                 ent->environment = ENV_SLIME;
554                         }
555                         else if (mapAttribute == MAP_LAVA)
556                         {
557                                 ent->environment = ENV_LAVA;
558                         }
559                         break;
560         }
561 }
562
563 void raiseWaterLevel()
564 {
565         if (map.waterLevel == map.requiredWaterLevel)
566         {
567                 return;
568         }
569
570         int y = (int)map.waterLevel;
571
572         if ((int)map.waterLevel != map.requiredWaterLevel)
573         {
574                 for (int x = 0 ; x < MAPWIDTH ; x++)
575                 {
576                         if ((map.data[x][y] == MAP_AIR) || (map.isLiquid(x, y)))
577                         {
578                                 map.data[x][y] = MAP_WATER;
579                         }
580                         
581                         if ((map.data[x][y] >= MAP_DECORATION) && (map.data[x][y] <= MAP_WATERANIM))
582                         {
583                                 map.data[x][y] = MAP_WATER;
584                         }
585                         
586                         if (map.data[x][y] >= MAP_TOPLAYER)
587                         {
588                                 map.data[x][y] = MAP_WATER;
589                         }
590                         
591                         if (map.data[x][y - 1] >= MAP_TOPLAYER)
592                         {
593                                 map.data[x][y] = MAP_WATER;
594                         }
595
596                         if ((map.data[x][y - 1] == MAP_AIR) || (map.isLiquid(x, y - 1)))
597                         {
598                                 map.data[x][y - 1] = MAP_WATERANIM;
599                         }
600                         
601                         if ((map.data[x][y - 1] >= MAP_DECORATION) && (map.data[x][y - 1] <= MAP_WATERANIM))
602                         {
603                                 map.data[x][y - 1] = MAP_WATERANIM;
604                         }
605                 }
606
607                 map.waterLevel -= 0.1;
608
609                 int x = (int)(player.x + player.dx) >> BRICKSHIFT;
610                 int y = (int)(player.y + player.height - 1) >> BRICKSHIFT;
611
612                 int mapAttribute = map.data[x][y];
613
614                 if ((mapAttribute == MAP_WATER) && (player.environment == MAP_AIR))
615                 {
616                         evaluateMapAttribute(&player, mapAttribute);
617                 }
618         }
619 }
620
621 void doWind()
622 {
623         map.windChangeTime--;
624         
625         if (map.windChangeTime <= 0)
626         {
627                 map.windPower = 0;
628                 
629                 if (Math::rrand(0, 1) == 0)
630                         map.windPower = Math::rrand(-3, 3);
631                         
632                 // change wind time
633                 map.windChangeTime = Math::rrand(60, 600);
634         }
635         
636         addWindParticles();
637 }
638
639 void parseMapDataLine(const char *line, int y)
640 {
641         int tileIndex = 0;
642         int x = 0;
643
644         while (true)
645         {
646                 sscanf(line, "%d", &tileIndex);
647
648                 map.data[x][y] = tileIndex;
649
650                 while (true)
651                 {
652                         line++;
653
654                         if (*line == ' ')
655                                 break;
656                 }
657
658                 x++;
659
660                 if (x == MAPWIDTH)
661                         break;
662         }
663 }
664
665 bool loadMapData(const char *filename)
666 {
667         map.clear();
668
669         if (!engine.loadData(filename))
670                 graphics.showErrorAndExit("The requested map '%s' was not found.", filename);
671
672         char *token = strtok((char*)engine.dataBuffer, "\n");
673         parseMapDataLine(token, 0);
674
675         int y = 1;
676
677         while (true)
678         {
679                 token = strtok(NULL, "\n");
680
681                 parseMapDataLine(token, y);
682
683                 y++;
684                 if (y == MAPHEIGHT)
685                         break;
686         }
687
688         getMapTokens();
689
690         adjustObjectives();
691         initMIAPhrases();
692
693         return true;
694 }