]> git.mxchange.org Git - quix0rs-blobwars.git/blob - src/mapEditor.cpp
Use snprintf() and strncpy().
[quix0rs-blobwars.git] / src / mapEditor.cpp
1 /*
2 Copyright (C) 2004 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 "mapEditor.h"
22
23 void drawMap(int mapX, int mapY)
24 {
25         SDL_Rect r;
26         int tile = 0;
27
28         for (int x = 0 ; x < 20 ; x++)
29         {
30                 for (int y = 0 ; y < 15 ; y++)
31                 {
32                         r.x = x * BRICKSIZE;
33                         r.y = y * BRICKSIZE;
34                         r.w = r.h = BRICKSIZE - 1;
35                         
36                         tile = map.data[x + mapX][y + mapY];
37                         
38                         if (tile == MAP_WATERANIM)
39                         {
40                                 tile = graphics.getWaterAnim();
41                         }
42
43                         if (tile > 0)
44                         {
45                                 graphics.blit(graphics.tile[tile], r.x, r.y, graphics.screen, false);
46                                 
47                                 if ((tile >= MAP_NORESET) && (tile < MAP_DECORATION))
48                                 {
49                                         graphics.drawRect(r.x, r.y, 32, 4, graphics.yellow, graphics.screen);
50                                 }
51                         }
52                 }
53         }
54 }
55
56 void showMap(int *mapX, int *mapY)
57 {
58         SDL_FillRect(graphics.screen, NULL, graphics.black);
59
60         engine.keyState[SDLK_SPACE] = 0;
61         int moveTimer = 0;
62
63         while (true)
64         {
65                 graphics.updateScreen();
66                 engine.getInput();
67                 config.populate();
68
69                 if (engine.keyState[SDLK_SPACE])
70                         break;
71                         
72                 for (int x = 0 ; x < MAPWIDTH ; x++)
73                 {
74                         for (int y = 0 ; y < MAPHEIGHT ; y++)
75                         {
76                                 switch (map.data[x][y])
77                                 {
78                                         case 0:
79                                                 graphics.putPixel(x, y, 9, graphics.screen);
80                                                 break;
81                                         case 1:
82                                                 graphics.putPixel(x, y,graphics.blue, graphics.screen);
83                                                 break;
84                                         case 2:
85                                                 graphics.putPixel(x, y, graphics.green, graphics.screen);
86                                                 break;
87                                         case 3:
88                                                 graphics.putPixel(x, y, graphics.red, graphics.screen);
89                                                 break;
90                                         default:
91                                                 graphics.putPixel(x, y, graphics.white, graphics.screen);
92                                                 break;
93                                 }
94                         }
95                 }
96
97                 if (moveTimer == 0)
98                 {
99                         if (engine.keyState[SDLK_LEFT])
100                                 *mapX -= 1;
101
102                         if (engine.keyState[SDLK_RIGHT])
103                                 *mapX += 1;
104
105                         if (engine.keyState[SDLK_UP])
106                                 *mapY -= 1;
107
108                         if (engine.keyState[SDLK_DOWN])
109                                 *mapY += 1;
110                 }
111
112                 moveTimer--;
113                 Math::limitInt(&moveTimer, 0, 60);
114
115                 graphics.drawRect(*mapX, *mapY, 20, 1, graphics.green, graphics.screen);
116                 graphics.drawRect(*mapX, *mapY, 1, 15, graphics.green, graphics.screen);
117                 graphics.drawRect(*mapX, *mapY + 15, 20, 1, graphics.green, graphics.screen);
118                 graphics.drawRect(*mapX + 20, *mapY, 1, 15, graphics.green, graphics.screen);
119
120                 SDL_Delay(16);
121         }
122
123         engine.keyState[SDLK_SPACE] = 0;
124 }
125
126 int nextBlock(int current, int dir)
127 {
128         if ((current + dir) > 255)
129                 return current;
130
131         if ((current + dir) < 0)
132                 return current;
133
134         int wanted = current;
135
136         while (true)
137         {
138                 wanted += dir;
139
140                 if (wanted < 0) return current;
141                 if (wanted > 255) return current;
142
143                 if (graphics.tile[wanted])
144                         return wanted;
145         }
146 }
147
148 void drawEnemies()
149 {
150         Entity *enemy = (Entity*)map.enemyList.getHead();
151
152         int x, y, absX, absY;
153
154         while (enemy->next != NULL)
155         {
156                 enemy = (Entity*)enemy->next;
157
158                 if (enemy->owner != enemy)
159                 {
160                         enemy->face = enemy->owner->face;
161                         (enemy->face == 0) ? enemy->x = enemy->owner->x + enemy->tx : enemy->x = enemy->owner->x + -enemy->tx;
162                         enemy->y = enemy->owner->y + enemy->ty;
163                 }
164
165                 x = (int)(enemy->x - engine.playerPosX);
166                 y = (int)(enemy->y - engine.playerPosY);
167
168                 absX = abs(x);
169                 absY = abs(y);
170
171                 if ((absX < 800) && (absY < 600))
172                 {
173                         graphics.blit(enemy->getFaceImage(), x, y, graphics.screen, false);
174                         enemy->animate();
175
176                         if ((!(enemy->flags & ENT_WEIGHTLESS)) && (!(enemy->flags & ENT_FLIES)) && (!(enemy->flags & ENT_SWIMS)))
177                                 enemy->applyGravity();
178                 }
179         }
180 }
181
182 void deleteEnemy(int x, int y)
183 {
184         x *= BRICKSIZE;
185         y *= BRICKSIZE;
186
187         Entity *enemy = (Entity*)map.enemyList.getHead();
188         Entity *previous = enemy;
189
190         while (enemy->next != NULL)
191         {
192                 enemy = (Entity*)enemy->next;
193
194                 if ((enemy->x == x) && (enemy->y == y))
195                 {
196                         map.enemyList.remove(previous, enemy);
197                         enemy = previous;
198                 }
199                 else
200                 {
201                         previous = enemy;
202                 }
203         }
204 }
205
206 void saveMap(const char *name)
207 {
208         FILE *fp = fopen(name, "wb");
209         Entity *enemy = (Entity*)map.enemyList.getHead();
210         String *str;
211
212         if (fp)
213         {
214                 for (int y = 0 ; y < MAPHEIGHT ; y++)
215                 {
216                         for (int x = 0 ; x < MAPWIDTH ; x++)
217                         {
218                                 fprintf(fp, "%d ", map.data[x][y]);
219                         }
220                         fprintf(fp, "\n");
221                 }
222
223                 str = stringHead->next;
224                 while (str != NULL)
225                 {
226                         fprintf(fp, "%s", str->string);
227                         str = str->next;
228                 }
229                 
230                 while (enemy->next != NULL)
231                 {
232                         enemy = (Entity*)enemy->next;
233                         fprintf(fp, "EMH ENEMY \"%s\" %d %d\n", enemy->name, (int)enemy->x, (int)enemy->y);
234                 }
235
236                 fprintf(fp, "@EOF@\n");
237
238                 fclose(fp);
239         }
240         
241         printf("Saved %s (%d)\n", name, SDL_GetTicks());
242 }
243
244 void collectMapData()
245 {
246         FILE *fp = fopen(game.mapName, "rb");
247         if (!fp)
248                 return;
249
250         char string[1024];
251         String *str;
252
253         for (int y = 0 ; y < 300 ; y++)
254                 fgets(string, 1024, fp);
255
256         while (true)
257         {
258                 fgets(string, 1024, fp);
259                 printf("Read: %s", string);
260
261                 if (strstr(string, "@EOF@"))
262                         break;
263
264                 if (!strstr(string, " ENEMY \""))
265                 {
266                         str = new String;
267                         strncpy(str->string, string, sizeof str->string);
268                         stringTail->next = str;
269                         stringTail = str;
270                 }
271                 
272                 if (strstr(string, "TILESET gfx/ancient"))
273                 {
274                         for (int x = 0 ; x < MAPWIDTH ; x++)
275                         {
276                                 for (int y = 0 ; y < MAPHEIGHT ; y++)
277                                 {
278                                         if ((map.data[x][y] >= 9) && (map.data[x][y] <= 20) && ((Math::prand() % 2) == 0))
279                                                 map.data[x][y] = Math::rrand(9, 20);
280                                 }
281                         }
282                 }
283                 
284                 if (strstr(string, "TILESET gfx/caves"))
285                 {
286                         for (int x = 0 ; x < MAPWIDTH ; x++)
287                         {
288                                 for (int y = 0 ; y < MAPHEIGHT ; y++)
289                                 {
290                                         if ((map.data[x][y] >= 9) && (map.data[x][y] <= 20))
291                                                 map.data[x][y] = Math::rrand(9, 12);
292                                 }
293                         }
294                 }
295         }
296
297         fclose(fp);
298 }
299
300 void newMap(const char *name)
301 {
302         FILE *fp = fopen(name, "wb");
303
304         if (fp)
305         {
306                 for (int y = 0 ; y < MAPHEIGHT ; y++)
307                 {
308                         for (int x = 0 ; x < MAPWIDTH ; x++)
309                         {
310                                 fprintf(fp, "%d ", map.data[x][y]);
311                         }
312                         fprintf(fp, "\n");
313                 }
314                 
315                 fprintf(fp, "EMH STAGENAME \"unnamed\"\n");
316
317                 fprintf(fp, "EMH TILESET gfx/grasslands\n");
318                 fprintf(fp, "EMH BACKGROUND gfx/grasslands/stone.jpg\n");
319                 fprintf(fp, "EMH MUSIC music/viking.mod\n");
320
321                 fprintf(fp, "EMH ALPHATILES 1 2 3 200 201 202 203 204 244 245 246 -1\n");
322
323                 fprintf(fp, "EMH START 10 10\n");
324
325                 fprintf(fp, "@EOF@\n");
326                 
327                 fclose(fp);
328         }
329         else
330         {
331                 exit(1);
332         }
333 }
334
335 void addTileDecoration()
336 {
337         printf("Adding Tile Decoration...\n");
338
339         for (int y = 1 ; y < MAPHEIGHT ; y++)
340         {
341                 for (int x = 0 ; x < MAPWIDTH ; x++)
342                 {
343                         if ((map.data[x][y] == 9) && (map.data[x][y - 1] == MAP_AIR))
344                         {
345                                 if (Math::prand() % 4)
346                                         map.data[x][y - 1] = 241;
347                         }
348                 }
349         }
350
351         for (int y = 0 ; y < MAPHEIGHT ; y++)
352         {
353                 for (int x = 0 ; x < MAPWIDTH ; x++)
354                 {
355                         if (map.data[x][y] == 241)
356                         {
357                                 if ((Math::prand() % 3) == 0)
358                                         map.data[x][y] = 242;
359                         }
360                 }
361         }
362         
363         engine.keyState[SDLK_F1] = 0;
364 }
365
366 void fillHorizontal(int block, int x, int y)
367 {
368         bool moveLeft = true;
369         bool moveRight = true;
370         bool ok = true;
371         
372         int left = x;
373         int right = x;
374         
375         if (map.data[x][y] == 0)
376         {
377                 map.data[x][y] = block;
378                 
379                 while (ok)
380                 {
381                         if (moveLeft)
382                         {
383                                 left--;
384                                 if (left < 0) 
385                                 {
386                                         left = 0;
387                                 }
388                         }
389                         
390                         if (map.data[left][y] == 0)
391                         {
392                                 map.data[left][y] = block;
393                         }
394                         else
395                         {
396                                 moveLeft = false;
397                         }
398                         
399                         if (moveRight)
400                         {
401                                 right++;
402                                 
403                                 if (right >= MAPWIDTH)
404                                 {
405                                         right = MAPWIDTH - 1;
406                                 }
407                         }
408                         
409                         if (map.data[right][y] == 0)
410                         {
411                                 map.data[right][y] = block;
412                         }
413                         else
414                         {
415                                 moveRight = false;
416                         }
417                         
418                         if ((!moveLeft) && (!moveRight))
419                         {
420                                 ok = false;
421                         }
422                 }
423         }
424 }
425
426 int main(int argc, char *argv[])
427 {
428         if (argc < 2)
429         {
430                 printf("Usage: mapeditor <filename>\n\n");
431                 exit(1);
432         }
433
434         atexit(cleanup);
435         
436         engine.useAudio = 0;
437
438         initSystem();
439
440         FILE *fp = fopen(argv[1], "rb");
441         if (!fp)
442                 newMap(argv[1]);
443         else
444                 fclose(fp);
445         
446         game.setMapName(argv[1]);
447         
448         loadResources();
449         
450         collectMapData();
451         
452         int mapX, mapY, allowMove, x, y;
453         mapX = mapY = allowMove = x = y = 0;
454         
455         int editing = 0;
456         int currentMonster = 0;
457         int currentItem = 0;
458         int currentBlock = 1;
459
460         SDL_Rect r;
461
462         int MOVESPEED = 5;
463         
464         char string[255];
465         
466         unsigned int frameLimit = SDL_GetTicks() + 16;
467
468         while (true)
469         {
470                 engine.getInput();
471                 config.populate();
472                 engine.doPause();
473                 engine.doFrameLoop();
474
475                 graphics.updateScreen();
476                 graphics.animateSprites();
477                 graphics.drawBackground();
478
479                 engine.setPlayerPosition((mapX * 32) + 320, (mapY * 32) + 240, map.limitLeft, map.limitRight, map.limitUp, map.limitDown);
480
481                 drawMap(mapX, mapY);
482                 doTrains();
483                 doSwitches();
484                 doItems();
485                 doBullets();
486                 doMIAs();
487                 drawEnemies();
488                 doObstacles();
489                 doEffects();
490                 doParticles();
491                 doTeleporters();
492                 doLineDefs();
493                 doTraps();
494
495                 x = engine.getMouseX();
496                 y = engine.getMouseY();
497
498                 x /= BRICKSIZE;
499                 y /= BRICKSIZE;
500
501                 r.x = x * BRICKSIZE;
502                 r.y = y * BRICKSIZE;
503                 r.w = BRICKSIZE;
504                 r.h = BRICKSIZE;
505
506                 switch (editing)
507                 {
508                         case 0:
509                                 graphics.drawRect(r.x - 1, r.y - 1, 34, 1, graphics.yellow, graphics.screen);
510                                 graphics.drawRect(r.x - 1, r.y - 1, 1, 34, graphics.yellow, graphics.screen);
511                                 graphics.drawRect(r.x + 32, r.y - 1, 1, 34, graphics.yellow, graphics.screen);
512                                 graphics.drawRect(r.x - 1, r.y + 32, 34, 1, graphics.yellow, graphics.screen);
513                                 graphics.blit(graphics.tile[currentBlock], r.x, r.y, graphics.screen, false);
514                                 if (engine.mouseLeft)
515                                         map.data[mapX + x][mapY + y] = currentBlock;
516                                 break;
517                         case 1:
518                                 graphics.blit(defEnemy[currentMonster].getFaceImage(), r.x, r.y, graphics.screen, false);
519                                 if (engine.mouseLeft)
520                                 {
521                                         addEnemy(defEnemy[currentMonster].name, (mapX + x) * BRICKSIZE, (mapY + y) * BRICKSIZE, 0);
522                                         engine.mouseLeft = 0;
523                                 }
524                                 break;
525                         case 2:
526                                 graphics.blit(defItem[currentItem].getFaceImage(), r.x, r.y, graphics.screen, false);
527                                 if (engine.mouseLeft)
528                                 {
529                                         addItem(defItem[currentItem].id, defItem[currentItem].name, (mapX + x) * BRICKSIZE, (mapY + y) * BRICKSIZE, defItem[currentItem].sprite[0]->name, 0, defItem[currentItem].value, 0, true);
530                                         engine.mouseLeft = 0;
531                                 }
532                                 break;
533                 }
534
535                 if (engine.mouseRight)
536                 {
537                         if (editing == 0) map.data[mapX + x][mapY + y] = MAP_AIR;
538                         if (editing == 1) deleteEnemy(mapX + x, mapY + y);
539                 }
540
541                 allowMove--;
542                 if (allowMove < 1) allowMove = 0;
543
544                 if (allowMove == 0)
545                 {
546                         if (engine.keyState[SDLK_UP]) {mapY--; allowMove = MOVESPEED;}
547                         if (engine.keyState[SDLK_DOWN]) {mapY++; allowMove = MOVESPEED;}
548                         if (engine.keyState[SDLK_LEFT]) {mapX--; allowMove = MOVESPEED;}
549                         if (engine.keyState[SDLK_RIGHT]) {mapX++; allowMove = MOVESPEED;}
550
551                         if (engine.keyState[SDLK_PAGEDOWN]) {mapY += 10; allowMove = MOVESPEED;}
552                         if (engine.keyState[SDLK_PAGEUP]) {mapY -= 10; allowMove = MOVESPEED;}
553
554                         if (engine.keyState[SDLK_1]) editing = 0;
555                         if (engine.keyState[SDLK_2]) editing = 1;
556                         if (engine.keyState[SDLK_3]) editing = 2;
557                         
558                         if (engine.keyState[SDLK_0]) fillHorizontal(currentBlock, mapX + x, mapY + y);
559
560                         if (engine.keyState[SDLK_F1]) addTileDecoration();
561
562                         if (engine.keyState[SDLK_ESCAPE]) break;
563                 }
564
565                 if (engine.keyState[SDLK_PERIOD])
566                 {
567                         switch (editing)
568                         {
569                                 case 0:
570                                         currentBlock = nextBlock(currentBlock, 1);
571                                         break;
572                                 case 1:
573                                         currentMonster++;
574                                         break;
575                                 case 2:
576                                         currentItem++;
577                                         break;
578                         }
579
580                         engine.keyState[SDLK_PERIOD] = 0;
581                 }
582
583                 if (engine.keyState[SDLK_COMMA])
584                 {
585                         switch (editing)
586                         {
587                                 case 0:
588                                         currentBlock = nextBlock(currentBlock, -1);
589                                         break;
590                                 case 1:
591                                         currentMonster--;
592                                         break;
593                                 case 2:
594                                         currentItem--;
595                                         break;
596                         }
597
598                         engine.keyState[SDLK_COMMA] = 0;
599                 }
600
601                 Math::limitInt(&currentMonster, 0, MAX_ENEMIES - 1);
602                 Math::limitInt(&currentItem, 0, MAX_ITEMS - 1);
603
604                 if (defEnemy[currentMonster].sprite[0] == NULL)
605                         currentMonster = 0;
606                         
607                 if (defItem[currentItem].sprite[0] == NULL)
608                         currentItem = 0;
609
610                 if (engine.keyState[SDLK_SPACE]) {showMap(&mapX, &mapY);}
611
612                 if (engine.keyState[SDLK_s]) {saveMap(game.mapName); engine.keyState[SDLK_s] = 0;}
613
614                 if (mapX < 0) mapX = 0;
615                 if (mapY < 0) mapY = 0;
616                 if (mapX > MAPWIDTH - 40) mapX = MAPWIDTH - 40;
617                 if (mapY > MAPHEIGHT - 30) mapY = MAPHEIGHT - 30;
618
619                 if (editing == 0)
620                         snprintf(string, sizeof string, "Index : %d:%d ; Screen %d:%d ; Tile %d", mapX + x, mapY + y, (mapX + x) * BRICKSIZE, (mapY + y) * BRICKSIZE, currentBlock);
621                 else if (editing == 1)
622                         snprintf(string, sizeof string, "Index : %d:%d ; Screen %d:%d ; %s", mapX + x, mapY + y, (mapX + x) * BRICKSIZE, (mapY + y) * BRICKSIZE, defEnemy[currentMonster].name);
623                 else if (editing == 2)
624                         snprintf(string, sizeof string, "Index : %d:%d ; Screen %d:%d ; %s", mapX + x, mapY + y, (mapX + x) * BRICKSIZE, (mapY + y) * BRICKSIZE, defItem[currentItem].name);
625
626                 r.x = 0;
627                 r.w = 640;
628                 r.h = 20;
629
630                 if (mapY < MAPHEIGHT - 30)
631                         r.y = 460;
632                 else
633                         r.y = 0;
634
635                 SDL_FillRect(graphics.screen, &r, graphics.black);
636
637                 graphics.drawString(string, 320, r.y + 5, true, graphics.screen);
638                 
639                 engine.delay(frameLimit);
640                 frameLimit = SDL_GetTicks() + 16;
641         }
642
643         String *str = stringHead->next;
644         String *str2;
645         while (str != NULL)
646         {
647                 str2 = str;
648                 printf("Deleting %s", str->string);
649                 str = str->next;
650                 delete str2;
651         }
652
653         return 0;
654 }