2 Copyright (C) 2004-2011 Parallel Realities
3 Copyright (C) 2011-2015 Perpendicular Dimensions
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"
24 MedalServer medalServer;
26 ReplayData replayData;
28 void drawMap(int mapX, int mapY)
33 for (int x = 0 ; x < 20 ; x++)
35 for (int y = 0 ; y < 15 ; y++)
39 r.w = r.h = BRICKSIZE - 1;
41 tile = map.data[x + mapX][y + mapY];
43 if (tile == MAP_WATERANIM)
45 tile = graphics.getWaterAnim();
50 graphics.blit(graphics.tile[tile], r.x, r.y, graphics.screen, false);
52 if ((tile >= MAP_NORESET) && (tile < MAP_DECORATION))
54 graphics.drawRect(r.x, r.y, 32, 4, graphics.yellow, graphics.screen);
61 void showMap(int *mapX, int *mapY)
63 SDL_FillRect(graphics.screen, NULL, graphics.black);
65 engine.keyState[SDL_SCANCODE_SPACE] = 0;
70 graphics.updateScreen();
74 if (engine.keyState[SDL_SCANCODE_SPACE])
77 for (int x = 0 ; x < MAPWIDTH ; x++)
79 for (int y = 0 ; y < MAPHEIGHT ; y++)
81 switch (map.data[x][y])
84 graphics.putPixel(x, y, 9, graphics.screen);
87 graphics.putPixel(x, y,graphics.blue, graphics.screen);
90 graphics.putPixel(x, y, graphics.green, graphics.screen);
93 graphics.putPixel(x, y, graphics.red, graphics.screen);
96 graphics.putPixel(x, y, graphics.white, graphics.screen);
104 if (engine.keyState[SDL_SCANCODE_LEFT])
107 if (engine.keyState[SDL_SCANCODE_RIGHT])
110 if (engine.keyState[SDL_SCANCODE_UP])
113 if (engine.keyState[SDL_SCANCODE_DOWN])
118 Math::limitInt(&moveTimer, 0, 60);
120 graphics.drawRect(*mapX, *mapY, 20, 1, graphics.green, graphics.screen);
121 graphics.drawRect(*mapX, *mapY, 1, 15, graphics.green, graphics.screen);
122 graphics.drawRect(*mapX, *mapY + 15, 20, 1, graphics.green, graphics.screen);
123 graphics.drawRect(*mapX + 20, *mapY, 1, 15, graphics.green, graphics.screen);
128 engine.keyState[SDL_SCANCODE_SPACE] = 0;
131 int nextBlock(int current, int dir)
133 if ((current + dir) > 255)
136 if ((current + dir) < 0)
139 int wanted = current;
145 if (wanted < 0) return current;
146 if (wanted > 255) return current;
148 if (graphics.tile[wanted])
155 Entity *enemy = (Entity*)map.enemyList.getHead();
157 int x, y, absX, absY;
159 while (enemy->next != NULL)
161 enemy = (Entity*)enemy->next;
163 if (enemy->owner != enemy)
165 enemy->face = enemy->owner->face;
166 (enemy->face == 0) ? enemy->x = enemy->owner->x + enemy->tx : enemy->x = enemy->owner->x + -enemy->tx;
167 enemy->y = enemy->owner->y + enemy->ty;
170 x = (int)(enemy->x - engine.playerPosX);
171 y = (int)(enemy->y - engine.playerPosY);
176 if ((absX < 800) && (absY < 600))
178 graphics.blit(enemy->getFaceImage(), x, y, graphics.screen, false);
181 if ((!(enemy->flags & ENT_WEIGHTLESS)) && (!(enemy->flags & ENT_FLIES)) && (!(enemy->flags & ENT_SWIMS)))
182 enemy->applyGravity();
187 void deleteEnemy(int x, int y)
192 Entity *enemy = (Entity*)map.enemyList.getHead();
193 Entity *previous = enemy;
195 while (enemy->next != NULL)
197 enemy = (Entity*)enemy->next;
199 if ((enemy->x == x) && (enemy->y == y))
201 map.enemyList.remove(previous, enemy);
211 void saveMap(const char *name)
213 FILE *fp = fopen(name, "wb");
214 Entity *enemy = (Entity*)map.enemyList.getHead();
219 for (int y = 0 ; y < MAPHEIGHT ; y++)
221 for (int x = 0 ; x < MAPWIDTH ; x++)
223 fprintf(fp, "%d ", map.data[x][y]);
228 str = stringHead->next;
231 fprintf(fp, "%s", str->string);
235 while (enemy->next != NULL)
237 enemy = (Entity*)enemy->next;
238 fprintf(fp, "EMH ENEMY \"%s\" %d %d\n", enemy->name, (int)enemy->x, (int)enemy->y);
241 fprintf(fp, "@EOF@\n");
246 printf("Saved %s (%d)\n", name, SDL_GetTicks());
249 void collectMapData()
251 FILE *fp = fopen(game.mapName, "rb");
258 for (int y = 0 ; y < 300 ; y++)
259 fgets(string, 1024, fp);
263 fgets(string, 1024, fp);
264 printf("Read: %s", string);
266 if (strstr(string, "@EOF@"))
269 if (!strstr(string, " ENEMY \""))
272 strlcpy(str->string, string, sizeof str->string);
273 stringTail->next = str;
277 if (strstr(string, "TILESET gfx/ancient"))
279 for (int x = 0 ; x < MAPWIDTH ; x++)
281 for (int y = 0 ; y < MAPHEIGHT ; y++)
283 if ((map.data[x][y] >= 9) && (map.data[x][y] <= 20) && ((Math::prand() % 2) == 0))
284 map.data[x][y] = Math::rrand(9, 20);
289 if (strstr(string, "TILESET gfx/caves"))
291 for (int x = 0 ; x < MAPWIDTH ; x++)
293 for (int y = 0 ; y < MAPHEIGHT ; y++)
295 if ((map.data[x][y] >= 9) && (map.data[x][y] <= 20))
296 map.data[x][y] = Math::rrand(9, 12);
305 void newMap(const char *name)
307 FILE *fp = fopen(name, "wb");
311 for (int y = 0 ; y < MAPHEIGHT ; y++)
313 for (int x = 0 ; x < MAPWIDTH ; x++)
315 fprintf(fp, "%d ", map.data[x][y]);
320 fprintf(fp, "EMH STAGENAME \"unnamed\"\n");
322 fprintf(fp, "EMH TILESET gfx/grasslands\n");
323 fprintf(fp, "EMH BACKGROUND gfx/grasslands/stone.jpg\n");
324 fprintf(fp, "EMH MUSIC music/tunnel\n");
326 fprintf(fp, "EMH ALPHATILES 1 2 3 200 201 202 203 204 244 245 246 -1\n");
328 fprintf(fp, "EMH START 10 10\n");
330 fprintf(fp, "@EOF@\n");
340 void addTileDecoration()
342 printf("Adding Tile Decoration...\n");
344 for (int y = 1 ; y < MAPHEIGHT ; y++)
346 for (int x = 0 ; x < MAPWIDTH ; x++)
348 if ((map.data[x][y] == 9) && (map.data[x][y - 1] == MAP_AIR))
350 if (Math::prand() % 4)
351 map.data[x][y - 1] = 241;
356 for (int y = 0 ; y < MAPHEIGHT ; y++)
358 for (int x = 0 ; x < MAPWIDTH ; x++)
360 if (map.data[x][y] == 241)
362 if ((Math::prand() % 3) == 0)
363 map.data[x][y] = 242;
368 engine.keyState[SDL_SCANCODE_F1] = 0;
371 void fillHorizontal(int block, int x, int y)
373 bool moveLeft = true;
374 bool moveRight = true;
380 if (map.data[x][y] == 0)
382 map.data[x][y] = block;
395 if (map.data[left][y] == 0)
397 map.data[left][y] = block;
408 if (right >= MAPWIDTH)
410 right = MAPWIDTH - 1;
414 if (map.data[right][y] == 0)
416 map.data[right][y] = block;
423 if ((!moveLeft) && (!moveRight))
431 int main(int argc, char *argv[])
435 printf("Usage: mapeditor <filename>\n\n");
439 config.engine = &engine;
449 FILE *fp = fopen(argv[1], "rb");
455 game.setMapName(argv[1]);
461 int mapX, mapY, allowMove, x, y;
462 mapX = mapY = allowMove = x = y = 0;
465 int currentMonster = 0;
467 int currentBlock = 1;
475 unsigned int frameLimit = SDL_GetTicks() + 16;
482 engine.doFrameLoop();
484 graphics.updateScreen();
485 graphics.animateSprites();
486 graphics.drawBackground();
488 engine.setPlayerPosition((mapX * 32) + 320, (mapY * 32) + 240, map.limitLeft, map.limitRight, map.limitUp, map.limitDown);
504 x = engine.getMouseX();
505 y = engine.getMouseY();
518 graphics.drawRect(r.x - 1, r.y - 1, 34, 1, graphics.yellow, graphics.screen);
519 graphics.drawRect(r.x - 1, r.y - 1, 1, 34, graphics.yellow, graphics.screen);
520 graphics.drawRect(r.x + 32, r.y - 1, 1, 34, graphics.yellow, graphics.screen);
521 graphics.drawRect(r.x - 1, r.y + 32, 34, 1, graphics.yellow, graphics.screen);
522 graphics.blit(graphics.tile[currentBlock], r.x, r.y, graphics.screen, false);
523 if (engine.mouseLeft)
524 map.data[mapX + x][mapY + y] = currentBlock;
527 graphics.blit(defEnemy[currentMonster].getFaceImage(), r.x, r.y, graphics.screen, false);
528 if (engine.mouseLeft)
530 addEnemy(defEnemy[currentMonster].name, (mapX + x) * BRICKSIZE, (mapY + y) * BRICKSIZE, 0);
531 engine.mouseLeft = 0;
535 graphics.blit(defItem[currentItem].getFaceImage(), r.x, r.y, graphics.screen, false);
536 if (engine.mouseLeft)
538 addItem(defItem[currentItem].id, defItem[currentItem].name, (mapX + x) * BRICKSIZE, (mapY + y) * BRICKSIZE, defItem[currentItem].sprite[0]->name, 0, defItem[currentItem].value, 0, true);
539 engine.mouseLeft = 0;
544 if (engine.mouseRight)
546 if (editing == 0) map.data[mapX + x][mapY + y] = MAP_AIR;
547 if (editing == 1) deleteEnemy(mapX + x, mapY + y);
551 if (allowMove < 1) allowMove = 0;
555 if (engine.keyState[SDL_SCANCODE_UP]) {mapY--; allowMove = MOVESPEED;}
556 if (engine.keyState[SDL_SCANCODE_DOWN]) {mapY++; allowMove = MOVESPEED;}
557 if (engine.keyState[SDL_SCANCODE_LEFT]) {mapX--; allowMove = MOVESPEED;}
558 if (engine.keyState[SDL_SCANCODE_RIGHT]) {mapX++; allowMove = MOVESPEED;}
560 if (engine.keyState[SDL_SCANCODE_PAGEDOWN]) {mapY += 10; allowMove = MOVESPEED;}
561 if (engine.keyState[SDL_SCANCODE_PAGEUP]) {mapY -= 10; allowMove = MOVESPEED;}
563 if (engine.keyState[SDL_SCANCODE_1]) editing = 0;
564 if (engine.keyState[SDL_SCANCODE_2]) editing = 1;
565 if (engine.keyState[SDL_SCANCODE_3]) editing = 2;
567 if (engine.keyState[SDL_SCANCODE_0]) fillHorizontal(currentBlock, mapX + x, mapY + y);
569 if (engine.keyState[SDL_SCANCODE_F1]) addTileDecoration();
571 if (engine.keyState[SDL_SCANCODE_ESCAPE]) break;
574 if (engine.keyState[SDL_SCANCODE_PERIOD])
579 currentBlock = nextBlock(currentBlock, 1);
589 engine.keyState[SDL_SCANCODE_PERIOD] = 0;
592 if (engine.keyState[SDL_SCANCODE_COMMA])
597 currentBlock = nextBlock(currentBlock, -1);
607 engine.keyState[SDL_SCANCODE_COMMA] = 0;
610 Math::limitInt(¤tMonster, 0, MAX_ENEMIES - 1);
611 Math::limitInt(¤tItem, 0, MAX_ITEMS - 1);
613 if (defEnemy[currentMonster].sprite[0] == NULL)
616 if (defItem[currentItem].sprite[0] == NULL)
619 if (engine.keyState[SDL_SCANCODE_SPACE]) {showMap(&mapX, &mapY);}
621 if (engine.keyState[SDL_SCANCODE_S]) {saveMap(game.mapName); engine.keyState[SDL_SCANCODE_S] = 0;}
623 if (mapX < 0) mapX = 0;
624 if (mapY < 0) mapY = 0;
625 if (mapX > MAPWIDTH - 40) mapX = MAPWIDTH - 40;
626 if (mapY > MAPHEIGHT - 30) mapY = MAPHEIGHT - 30;
629 snprintf(string, sizeof string, "Index : %d:%d ; Screen %d:%d ; Tile %d", mapX + x, mapY + y, (mapX + x) * BRICKSIZE, (mapY + y) * BRICKSIZE, currentBlock);
630 else if (editing == 1)
631 snprintf(string, sizeof string, "Index : %d:%d ; Screen %d:%d ; %s", mapX + x, mapY + y, (mapX + x) * BRICKSIZE, (mapY + y) * BRICKSIZE, defEnemy[currentMonster].name);
632 else if (editing == 2)
633 snprintf(string, sizeof string, "Index : %d:%d ; Screen %d:%d ; %s", mapX + x, mapY + y, (mapX + x) * BRICKSIZE, (mapY + y) * BRICKSIZE, defItem[currentItem].name);
639 if (mapY < MAPHEIGHT - 30)
644 SDL_FillRect(graphics.screen, &r, graphics.black);
646 graphics.drawString(string, 320, r.y + 5, true, graphics.screen);
648 engine.delay(frameLimit);
649 frameLimit = SDL_GetTicks() + 16;
652 String *str = stringHead->next;
657 printf("Deleting %s", str->string);