Some Window$ specific edits.
[dbw.git] / src / mapEditor.cpp
blob0ab305db29633b7b5c26482f12beace7d7e6b624
1 /*
2 Copyright (C) 2004 Parallel Realities
3 Copyright (C) 2007 Kővágó Zoltán
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 See the GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 #include "mapEditor.h"
23 #include "physfs/physfs.hpp"
25 void drawMap(int mapX, int mapY)
27 SDL_Rect r;
28 int tile = 0;
30 map.offsetX = mapX*32;
31 map.offsetY = mapY*32;
33 int xtimes = (graphics.width / 32) + (graphics.width % 32 ? 2 : 1);
34 int ytimes = (graphics.height / 32) + (graphics.width % 32 ? 2 : 1);
36 int mapx = map.offsetX >> BRICKSHIFT;
37 int mapy = map.offsetY >> BRICKSHIFT;
39 for (int x = 0 ; (x < xtimes) && ((mapx+x) < MAPWIDTH) ; x++)
41 for (int y = 0 ; (y < ytimes) && ((mapy + y) < MAPHEIGHT) ; y++)
43 r.x = x * BRICKSIZE;
44 r.y = y * BRICKSIZE;
45 r.w = r.h = BRICKSIZE - 1;
47 tile = map.data[x + mapX][y + mapY];
49 if (tile == MAP_WATERANIM)
51 tile = graphics.getWaterAnim();
54 if (tile > 0)
56 graphics.blit(graphics.tile[tile], r.x, r.y, graphics.screen, false);
58 if ((tile >= MAP_NORESET) && (tile < MAP_DECORATION))
60 graphics.drawRect(r.x, r.y, 32, 4, graphics.yellow, graphics.screen);
67 void showMap(int *mapX, int *mapY)
69 SDL_FillRect(graphics.screen, NULL, graphics.black);
71 engine.keyState[SDLK_SPACE] = 0;
72 int moveTimer = 0;
74 while (true)
76 graphics.updateScreen();
77 engine.getInput();
79 if (engine.keyState[SDLK_SPACE])
80 break;
82 for (int x = 0 ; x < MAPWIDTH ; x++)
84 for (int y = 0 ; y < MAPHEIGHT ; y++)
86 switch (map.data[x][y])
88 case 0:
89 graphics.putPixel(x, y, 9, graphics.screen);
90 break;
91 case 1:
92 graphics.putPixel(x, y,graphics.blue, graphics.screen);
93 break;
94 case 2:
95 graphics.putPixel(x, y, graphics.green, graphics.screen);
96 break;
97 case 3:
98 graphics.putPixel(x, y, graphics.red, graphics.screen);
99 break;
100 default:
101 graphics.putPixel(x, y, graphics.white, graphics.screen);
102 break;
107 if (moveTimer == 0)
109 if (engine.keyState[SDLK_LEFT])
110 *mapX -= 1;
112 if (engine.keyState[SDLK_RIGHT])
113 *mapX += 1;
115 if (engine.keyState[SDLK_UP])
116 *mapY -= 1;
118 if (engine.keyState[SDLK_DOWN])
119 *mapY += 1;
122 moveTimer--;
123 Math::limitInt(&moveTimer, 0, 60);
125 graphics.drawRect(*mapX, *mapY, graphics.width/32, 1, graphics.green, graphics.screen);
126 graphics.drawRect(*mapX, *mapY, 1, graphics.height/32, graphics.green, graphics.screen);
127 graphics.drawRect(*mapX, *mapY + graphics.height/32, graphics.width/32, 1, graphics.green, graphics.screen);
128 graphics.drawRect(*mapX + graphics.width/32, *mapY, 1, graphics.height/32, graphics.green, graphics.screen);
130 SDL_Delay(16);
133 engine.keyState[SDLK_SPACE] = 0;
136 int nextBlock(int current, int dir)
138 if ((current + dir) > 255)
139 return current;
141 if ((current + dir) < 0)
142 return current;
144 int wanted = current;
146 while (true)
148 wanted += dir;
150 if (wanted < 0) return current;
151 if (wanted > 255) return current;
153 if (graphics.tile[wanted])
154 return wanted;
158 void drawEnemies()
160 Entity *enemy = (Entity*)map.enemyList.getHead();
162 int x, y, absX, absY;
164 while (enemy->next != NULL)
166 enemy = (Entity*)enemy->next;
168 if (enemy->owner != enemy)
170 enemy->face = enemy->owner->face;
171 (enemy->face == 0) ? enemy->x = enemy->owner->x + enemy->tx : enemy->x = enemy->owner->x + -enemy->tx;
172 enemy->y = enemy->owner->y + enemy->ty;
175 x = (int)(enemy->x - map.offsetX);
176 y = (int)(enemy->y - map.offsetY);
178 absX = abs(x);
179 absY = abs(y);
181 if ((absX < (graphics.width + 160)) && (absY < (graphics.height + 120)))
183 graphics.blit(enemy->getFaceImage(), x, y, graphics.screen, false);
184 enemy->animate();
186 if ((!(enemy->flags & ENT_WEIGHTLESS)) && (!(enemy->flags & ENT_FLIES)) && (!(enemy->flags & ENT_SWIMS)))
187 enemy->applyGravity();
192 void deleteEnemy(int x, int y)
194 x *= BRICKSIZE;
195 y *= BRICKSIZE;
197 Entity *enemy = (Entity*)map.enemyList.getHead();
198 Entity *previous = enemy;
200 while (enemy->next != NULL)
202 enemy = (Entity*)enemy->next;
204 if ((enemy->x == x) && (enemy->y == y))
206 map.enemyList.remove(previous, enemy);
207 enemy = previous;
209 else
211 previous = enemy;
216 void saveMap(char *name)
218 Entity *enemy = (Entity*)map.enemyList.getHead();
219 String *str;
221 PhysFS::OStream os(name);
223 for (int y = 0 ; y < MAPHEIGHT ; y++)
225 for (int x = 0 ; x < MAPWIDTH ; x++)
227 os << (int) map.data[x][y] << " ";
229 os << std::endl;
232 str = stringHead->next;
233 while (str != NULL)
235 os << str->string;
236 str = str->next;
239 while (enemy->next != NULL)
241 enemy = (Entity*)enemy->next;
242 os << "EMH ENEMY \"" << enemy->name << "\" " << enemy->x << " " << enemy->y << std::endl;
245 os << "@EOF@" << std::endl;
247 printf("Saved %s (%d)\n", name, SDL_GetTicks());
250 void collectMapData()
252 PhysFS::IStream is(game.mapName);
254 char string[1024];
255 String *str;
257 for (int y = 0 ; y < 300 ; y++)
259 is.ignore(102400, '\n');
262 while (is.good())
264 is.getline(string, 1022);
265 for (int i = 0; i < 1024; i++)
266 if (string[i] == 0)
268 string[i] = '\n';
269 string[i+1] = '\0';
270 break;
273 printf("Read: %s", string);
275 if (strstr(string, "@EOF@"))
276 break;
278 if (!strstr(string, " ENEMY \""))
280 str = new String;
281 strcpy(str->string, string);
282 stringTail->next = str;
283 stringTail = str;
286 if (strstr(string, "TILESET gfx/ancient"))
288 for (int x = 0 ; x < MAPWIDTH ; x++)
290 for (int y = 0 ; y < MAPHEIGHT ; y++)
292 if ((map.data[x][y] >= 9) && (map.data[x][y] <= 20) && ((rand() % 2) == 0))
293 map.data[x][y] = Math::rrand(9, 20);
298 if (strstr(string, "TILESET gfx/caves"))
300 for (int x = 0 ; x < MAPWIDTH ; x++)
302 for (int y = 0 ; y < MAPHEIGHT ; y++)
304 if ((map.data[x][y] >= 9) && (map.data[x][y] <= 20))
305 map.data[x][y] = Math::rrand(9, 12);
313 void newMap(char *name)
315 PhysFS::OStream os(name);
317 for (int y = 0 ; y < MAPHEIGHT ; y++)
319 for (int x = 0 ; x < MAPWIDTH ; x++)
321 os << map.data[x][y] << " ";
323 os << std::endl;
326 os << "EMH STAGENAME \"unnamed\"" << std::endl;
328 os << "EMH TILESET gfx/grasslands" << std::endl;
329 os << "EMH BACKGROUND gfx/grasslands/stone.jpg" << std::endl;
330 os << "EMH MUSIC music/viking.mod" << std::endl;
331 os << "EMH ALPHATITLES 1 2 3 200 201 202 203 204 244 245 246 -1" << std::endl;
332 os << "EMH START 10 10" << std::endl;
334 os << "@EOF@" << std::endl;
337 void addTileDecoration()
339 printf("Adding Tile Decoration...\n");
341 for (int y = 1 ; y < MAPHEIGHT ; y++)
343 for (int x = 0 ; x < MAPWIDTH ; x++)
345 if ((map.data[x][y] == 9) && (map.data[x][y - 1] == MAP_AIR))
347 if (rand() % 4)
348 map.data[x][y - 1] = 241;
353 for (int y = 0 ; y < MAPHEIGHT ; y++)
355 for (int x = 0 ; x < MAPWIDTH ; x++)
357 if (map.data[x][y] == 241)
359 if ((rand() % 3) == 0)
360 map.data[x][y] = 242;
365 engine.keyState[SDLK_F1] = 0;
368 void fillHorizontal(int block, int x, int y)
370 bool moveLeft = true;
371 bool moveRight = true;
372 bool ok = true;
374 int left = x;
375 int right = x;
377 if (map.data[x][y] == 0)
379 map.data[x][y] = block;
381 while (ok)
383 if (moveLeft)
385 left--;
386 if (left < 0)
388 left = 0;
392 if (map.data[left][y] == 0)
394 map.data[left][y] = block;
396 else
398 moveLeft = false;
401 if (moveRight)
403 right++;
405 if (right >= MAPWIDTH)
407 right = MAPWIDTH - 1;
411 if (map.data[right][y] == 0)
413 map.data[right][y] = block;
415 else
417 moveRight = false;
420 if ((!moveLeft) && (!moveRight))
422 ok = false;
428 int main(int argc, char *argv[])
430 if (argc != 2)
432 printf("Usage: mapeditor <filename>\n\n");
433 exit(1);
436 atexit(cleanup);
438 engine.useAudio = 0;
440 initSystem(argv[0]);
442 if (!PhysFS::instance->FileExists(argv[1]))
443 newMap(argv[1]);
445 game.setMapName(argv[1]);
447 loadResources();
449 collectMapData();
451 int mapX, mapY, allowMove, x, y;
452 mapX = mapY = allowMove = x = y = 0;
454 int editing = 0;
455 int currentMonster = 0;
456 int currentItem = 0;
457 int currentBlock = 1;
459 SDL_Rect r;
461 int MOVESPEED = 5;
463 char string[255];
465 unsigned int frameLimit = SDL_GetTicks() + 16;
467 while (true)
469 engine.getInput();
470 engine.doPause();
471 engine.doFrameLoop();
473 graphics.updateScreen();
474 graphics.animateSprites();
475 graphics.drawBackground();
477 engine.setPlayerPosition((mapX * 32) + 320, (mapY * 32) + 240, map.limitLeft, map.limitRight, map.limitUp, map.limitDown);
479 drawMap(mapX, mapY);
480 doTrains();
481 doSwitches();
482 doItems();
483 doBullets();
484 doMIAs();
485 drawEnemies();
486 doObstacles();
487 doEffects();
488 doParticles();
489 doTeleporters();
490 doLineDefs();
491 doTraps();
493 x = engine.getMouseX();
494 y = engine.getMouseY();
496 x /= BRICKSIZE;
497 y /= BRICKSIZE;
499 r.x = x * BRICKSIZE;
500 r.y = y * BRICKSIZE;
501 r.w = BRICKSIZE;
502 r.h = BRICKSIZE;
504 switch (editing)
506 case 0:
507 graphics.drawRect(r.x - 1, r.y - 1, 34, 1, graphics.yellow, graphics.screen);
508 graphics.drawRect(r.x - 1, r.y - 1, 1, 34, graphics.yellow, graphics.screen);
509 graphics.drawRect(r.x + 32, r.y - 1, 1, 34, graphics.yellow, graphics.screen);
510 graphics.drawRect(r.x - 1, r.y + 32, 34, 1, graphics.yellow, graphics.screen);
511 graphics.blit(graphics.tile[currentBlock], r.x, r.y, graphics.screen, false);
512 if (engine.mouseLeft)
513 map.data[mapX + x][mapY + y] = currentBlock;
514 break;
515 case 1:
516 graphics.blit(defEnemy[currentMonster].getFaceImage(), r.x, r.y, graphics.screen, false);
517 if (engine.mouseLeft)
519 addEnemy(defEnemy[currentMonster].name, (mapX + x) * BRICKSIZE, (mapY + y) * BRICKSIZE, 0);
520 engine.mouseLeft = 0;
522 break;
523 case 2:
524 graphics.blit(defItem[currentItem].getFaceImage(), r.x, r.y, graphics.screen, false);
525 if (engine.mouseLeft)
527 addItem(defItem[currentItem].id, defItem[currentItem].name, (mapX + x) * BRICKSIZE, (mapY + y) * BRICKSIZE, defItem[currentItem].sprite[0]->name, 0, defItem[currentItem].value, 0, true);
528 engine.mouseLeft = 0;
530 break;
533 if (engine.mouseRight)
535 if (editing == 0) map.data[mapX + x][mapY + y] = MAP_AIR;
536 if (editing == 1) deleteEnemy(mapX + x, mapY + y);
539 allowMove--;
540 if (allowMove < 1) allowMove = 0;
542 if (allowMove == 0)
544 if (engine.keyState[SDLK_UP]) {mapY--; allowMove = MOVESPEED;}
545 if (engine.keyState[SDLK_DOWN]) {mapY++; allowMove = MOVESPEED;}
546 if (engine.keyState[SDLK_LEFT]) {mapX--; allowMove = MOVESPEED;}
547 if (engine.keyState[SDLK_RIGHT]) {mapX++; allowMove = MOVESPEED;}
549 if (engine.keyState[SDLK_PAGEDOWN]) {mapY += 10; allowMove = MOVESPEED;}
550 if (engine.keyState[SDLK_PAGEUP]) {mapY -= 10; allowMove = MOVESPEED;}
552 if (engine.keyState[SDLK_1]) editing = 0;
553 if (engine.keyState[SDLK_2]) editing = 1;
554 if (engine.keyState[SDLK_3]) editing = 2;
556 if (engine.keyState[SDLK_0]) fillHorizontal(currentBlock, mapX + x, mapY + y);
558 if (engine.keyState[SDLK_F1]) addTileDecoration();
560 if (engine.keyState[SDLK_ESCAPE]) break;
563 if (engine.keyState[SDLK_PERIOD])
565 switch (editing)
567 case 0:
568 currentBlock = nextBlock(currentBlock, 1);
569 break;
570 case 1:
571 currentMonster++;
572 break;
573 case 2:
574 currentItem++;
575 break;
578 engine.keyState[SDLK_PERIOD] = 0;
581 if (engine.keyState[SDLK_COMMA])
583 switch (editing)
585 case 0:
586 currentBlock = nextBlock(currentBlock, -1);
587 break;
588 case 1:
589 currentMonster--;
590 break;
591 case 2:
592 currentItem--;
593 break;
596 engine.keyState[SDLK_COMMA] = 0;
599 Math::limitInt(&currentMonster, 0, MAX_ENEMIES - 1);
600 Math::limitInt(&currentItem, 0, MAX_ITEMS - 1);
602 if (defEnemy[currentMonster].sprite[0] == NULL)
603 currentMonster = 0;
605 if (defItem[currentItem].sprite[0] == NULL)
606 currentItem = 0;
608 if (engine.keyState[SDLK_SPACE]) {showMap(&mapX, &mapY);}
610 if (engine.keyState[SDLK_s]) {saveMap(game.mapName); engine.keyState[SDLK_s] = 0;}
612 if (mapX < 0) mapX = 0;
613 if (mapY < 0) mapY = 0;
614 if (mapX > MAPWIDTH - 40) mapX = MAPWIDTH - 40;
615 if (mapY > MAPHEIGHT - 30) mapY = MAPHEIGHT - 30;
617 if (editing == 0)
618 sprintf(string, "Index : %d:%d ; Screen %d:%d ; Tile %d", mapX + x, mapY + y, (mapX + x) * BRICKSIZE, (mapY + y) * BRICKSIZE, currentBlock);
619 else if (editing == 1)
620 sprintf(string, "Index : %d:%d ; Screen %d:%d ; %s", mapX + x, mapY + y, (mapX + x) * BRICKSIZE, (mapY + y) * BRICKSIZE, defEnemy[currentMonster].name);
621 else if (editing == 2)
622 sprintf(string, "Index : %d:%d ; Screen %d:%d ; %s", mapX + x, mapY + y, (mapX + x) * BRICKSIZE, (mapY + y) * BRICKSIZE,
623 defItem[currentItem].name);
625 r.x = 0;
626 r.w = graphics.width;
627 r.h = 20;
629 if (mapY < MAPHEIGHT - 30)
630 r.y = graphics.height - 20;
631 else
632 r.y = 0;
634 SDL_FillRect(graphics.screen, &r, graphics.black);
636 graphics.drawString(string, bx + 320, r.y + 5, true, graphics.screen);
638 engine.delay(frameLimit);
639 frameLimit = SDL_GetTicks() + 16;
642 String *str = stringHead->next;
643 String *str2;
644 while (str != NULL)
646 str2 = str;
647 printf("Deleting %s", str->string);
648 str = str->next;
649 delete str2;
652 return 0;