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