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