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 String *stringHead = new String;
25 String *stringTail = stringHead;
34 Entity defEnemy[MAX_ENEMIES];
35 Entity defItem[MAX_ITEMS];
37 Weapon weapon[MAX_WEAPONS];
39 MedalServer medalServer;
41 ReplayData replayData;
43 void drawMap(int mapX, int mapY)
48 for (int x = 0 ; x < 20 ; x++)
50 for (int y = 0 ; y < 15 ; y++)
54 r.w = r.h = BRICKSIZE - 1;
56 tile = map.data[x + mapX][y + mapY];
58 if (tile == MAP_WATERANIM)
60 tile = graphics.getWaterAnim();
65 graphics.blit(graphics.tile[tile], r.x, r.y, graphics.screen, false);
67 if ((tile >= MAP_NORESET) && (tile < MAP_DECORATION))
69 graphics.drawRect(r.x, r.y, 32, 4, graphics.yellow, graphics.screen);
76 void showMap(int *mapX, int *mapY)
78 SDL_FillRect(graphics.screen, NULL, graphics.black);
80 engine.keyState[SDL_SCANCODE_SPACE] = 0;
85 graphics.updateScreen();
89 if (engine.keyState[SDL_SCANCODE_SPACE])
92 for (int x = 0 ; x < MAPWIDTH ; x++)
94 for (int y = 0 ; y < MAPHEIGHT ; y++)
96 switch (map.data[x][y])
99 graphics.putPixel(x, y, 9, graphics.screen);
102 graphics.putPixel(x, y,graphics.blue, graphics.screen);
105 graphics.putPixel(x, y, graphics.green, graphics.screen);
108 graphics.putPixel(x, y, graphics.red, graphics.screen);
111 graphics.putPixel(x, y, graphics.white, graphics.screen);
119 if (engine.keyState[SDL_SCANCODE_LEFT])
122 if (engine.keyState[SDL_SCANCODE_RIGHT])
125 if (engine.keyState[SDL_SCANCODE_UP])
128 if (engine.keyState[SDL_SCANCODE_DOWN])
133 Math::limitInt(&moveTimer, 0, 60);
135 graphics.drawRect(*mapX, *mapY, 20, 1, graphics.green, graphics.screen);
136 graphics.drawRect(*mapX, *mapY, 1, 15, graphics.green, graphics.screen);
137 graphics.drawRect(*mapX, *mapY + 15, 20, 1, graphics.green, graphics.screen);
138 graphics.drawRect(*mapX + 20, *mapY, 1, 15, graphics.green, graphics.screen);
143 engine.keyState[SDL_SCANCODE_SPACE] = 0;
146 int nextBlock(int current, int dir)
148 if ((current + dir) > 255)
151 if ((current + dir) < 0)
154 int wanted = current;
160 if (wanted < 0) return current;
161 if (wanted > 255) return current;
163 if (graphics.tile[wanted])
170 Entity *enemy = (Entity*)map.enemyList.getHead();
172 int x, y, absX, absY;
174 while (enemy->next != NULL)
176 enemy = (Entity*)enemy->next;
178 if (enemy->owner != enemy)
180 enemy->face = enemy->owner->face;
181 (enemy->face == 0) ? enemy->x = enemy->owner->x + enemy->tx : enemy->x = enemy->owner->x + -enemy->tx;
182 enemy->y = enemy->owner->y + enemy->ty;
185 x = (int)(enemy->x - engine.playerPosX);
186 y = (int)(enemy->y - engine.playerPosY);
191 if ((absX < 800) && (absY < 600))
193 graphics.blit(enemy->getFaceImage(), x, y, graphics.screen, false);
196 if ((!(enemy->flags & ENT_WEIGHTLESS)) && (!(enemy->flags & ENT_FLIES)) && (!(enemy->flags & ENT_SWIMS)))
197 enemy->applyGravity();
202 void deleteEnemy(int x, int y)
207 Entity *enemy = (Entity*)map.enemyList.getHead();
208 Entity *previous = enemy;
210 while (enemy->next != NULL)
212 enemy = (Entity*)enemy->next;
214 if ((enemy->x == x) && (enemy->y == y))
216 map.enemyList.remove(previous, enemy);
226 void saveMap(const char *name)
228 FILE *fp = fopen(name, "wb");
229 Entity *enemy = (Entity*)map.enemyList.getHead();
234 for (int y = 0 ; y < MAPHEIGHT ; y++)
236 for (int x = 0 ; x < MAPWIDTH ; x++)
238 fprintf(fp, "%d ", map.data[x][y]);
243 str = stringHead->next;
246 fprintf(fp, "%s", str->string);
250 while (enemy->next != NULL)
252 enemy = (Entity*)enemy->next;
253 fprintf(fp, "EMH ENEMY \"%s\" %d %d\n", enemy->name, (int)enemy->x, (int)enemy->y);
256 fprintf(fp, "@EOF@\n");
261 printf("Saved %s (%d)\n", name, SDL_GetTicks());
264 void collectMapData()
266 FILE *fp = fopen(game.mapName, "rb");
273 for (int y = 0 ; y < 300 ; y++)
274 fgets(string, 1024, fp);
278 fgets(string, 1024, fp);
279 printf("Read: %s", string);
281 if (strstr(string, "@EOF@"))
284 if (!strstr(string, " ENEMY \""))
287 strlcpy(str->string, string, sizeof str->string);
288 stringTail->next = str;
292 if (strstr(string, "TILESET gfx/ancient"))
294 for (int x = 0 ; x < MAPWIDTH ; x++)
296 for (int y = 0 ; y < MAPHEIGHT ; y++)
298 if ((map.data[x][y] >= 9) && (map.data[x][y] <= 20) && ((Math::prand() % 2) == 0))
299 map.data[x][y] = Math::rrand(9, 20);
304 if (strstr(string, "TILESET gfx/caves"))
306 for (int x = 0 ; x < MAPWIDTH ; x++)
308 for (int y = 0 ; y < MAPHEIGHT ; y++)
310 if ((map.data[x][y] >= 9) && (map.data[x][y] <= 20))
311 map.data[x][y] = Math::rrand(9, 12);
320 void newMap(const char *name)
322 FILE *fp = fopen(name, "wb");
326 for (int y = 0 ; y < MAPHEIGHT ; y++)
328 for (int x = 0 ; x < MAPWIDTH ; x++)
330 fprintf(fp, "%d ", map.data[x][y]);
335 fprintf(fp, "EMH STAGENAME \"unnamed\"\n");
337 fprintf(fp, "EMH TILESET gfx/grasslands\n");
338 fprintf(fp, "EMH BACKGROUND gfx/grasslands/stone.jpg\n");
339 fprintf(fp, "EMH MUSIC music/tunnel\n");
341 fprintf(fp, "EMH ALPHATILES 1 2 3 200 201 202 203 204 244 245 246 -1\n");
343 fprintf(fp, "EMH START 10 10\n");
345 fprintf(fp, "@EOF@\n");
355 void addTileDecoration()
357 printf("Adding Tile Decoration...\n");
359 for (int y = 1 ; y < MAPHEIGHT ; y++)
361 for (int x = 0 ; x < MAPWIDTH ; x++)
363 if ((map.data[x][y] == 9) && (map.data[x][y - 1] == MAP_AIR))
365 if (Math::prand() % 4)
366 map.data[x][y - 1] = 241;
371 for (int y = 0 ; y < MAPHEIGHT ; y++)
373 for (int x = 0 ; x < MAPWIDTH ; x++)
375 if (map.data[x][y] == 241)
377 if ((Math::prand() % 3) == 0)
378 map.data[x][y] = 242;
383 engine.keyState[SDL_SCANCODE_F1] = 0;
386 void fillHorizontal(int block, int x, int y)
388 bool moveLeft = true;
389 bool moveRight = true;
395 if (map.data[x][y] == 0)
397 map.data[x][y] = block;
410 if (map.data[left][y] == 0)
412 map.data[left][y] = block;
423 if (right >= MAPWIDTH)
425 right = MAPWIDTH - 1;
429 if (map.data[right][y] == 0)
431 map.data[right][y] = block;
438 if ((!moveLeft) && (!moveRight))
446 int main(int argc, char *argv[])
450 printf("Usage: mapeditor <filename>\n\n");
454 config.engine = &engine;
464 FILE *fp = fopen(argv[1], "rb");
470 game.setMapName(argv[1]);
476 int mapX, mapY, allowMove, x, y;
477 mapX = mapY = allowMove = x = y = 0;
480 int currentMonster = 0;
482 int currentBlock = 1;
490 unsigned int frameLimit = SDL_GetTicks() + 16;
497 engine.doFrameLoop();
499 graphics.updateScreen();
500 graphics.animateSprites();
501 graphics.drawBackground();
503 engine.setPlayerPosition((mapX * 32) + 320, (mapY * 32) + 240, map.limitLeft, map.limitRight, map.limitUp, map.limitDown);
519 x = engine.getMouseX();
520 y = engine.getMouseY();
533 graphics.drawRect(r.x - 1, r.y - 1, 34, 1, graphics.yellow, graphics.screen);
534 graphics.drawRect(r.x - 1, r.y - 1, 1, 34, graphics.yellow, graphics.screen);
535 graphics.drawRect(r.x + 32, r.y - 1, 1, 34, graphics.yellow, graphics.screen);
536 graphics.drawRect(r.x - 1, r.y + 32, 34, 1, graphics.yellow, graphics.screen);
537 graphics.blit(graphics.tile[currentBlock], r.x, r.y, graphics.screen, false);
538 if (engine.mouseLeft)
539 map.data[mapX + x][mapY + y] = currentBlock;
542 graphics.blit(defEnemy[currentMonster].getFaceImage(), r.x, r.y, graphics.screen, false);
543 if (engine.mouseLeft)
545 addEnemy(defEnemy[currentMonster].name, (mapX + x) * BRICKSIZE, (mapY + y) * BRICKSIZE, 0);
546 engine.mouseLeft = 0;
550 graphics.blit(defItem[currentItem].getFaceImage(), r.x, r.y, graphics.screen, false);
551 if (engine.mouseLeft)
553 addItem(defItem[currentItem].id, defItem[currentItem].name, (mapX + x) * BRICKSIZE, (mapY + y) * BRICKSIZE, defItem[currentItem].sprite[0]->name, 0, defItem[currentItem].value, 0, true);
554 engine.mouseLeft = 0;
559 if (engine.mouseRight)
561 if (editing == 0) map.data[mapX + x][mapY + y] = MAP_AIR;
562 if (editing == 1) deleteEnemy(mapX + x, mapY + y);
566 if (allowMove < 1) allowMove = 0;
570 if (engine.keyState[SDL_SCANCODE_UP]) {mapY--; allowMove = MOVESPEED;}
571 if (engine.keyState[SDL_SCANCODE_DOWN]) {mapY++; allowMove = MOVESPEED;}
572 if (engine.keyState[SDL_SCANCODE_LEFT]) {mapX--; allowMove = MOVESPEED;}
573 if (engine.keyState[SDL_SCANCODE_RIGHT]) {mapX++; allowMove = MOVESPEED;}
575 if (engine.keyState[SDL_SCANCODE_PAGEDOWN]) {mapY += 10; allowMove = MOVESPEED;}
576 if (engine.keyState[SDL_SCANCODE_PAGEUP]) {mapY -= 10; allowMove = MOVESPEED;}
578 if (engine.keyState[SDL_SCANCODE_1]) editing = 0;
579 if (engine.keyState[SDL_SCANCODE_2]) editing = 1;
580 if (engine.keyState[SDL_SCANCODE_3]) editing = 2;
582 if (engine.keyState[SDL_SCANCODE_0]) fillHorizontal(currentBlock, mapX + x, mapY + y);
584 if (engine.keyState[SDL_SCANCODE_F1]) addTileDecoration();
586 if (engine.keyState[SDL_SCANCODE_ESCAPE]) break;
589 if (engine.keyState[SDL_SCANCODE_PERIOD])
594 currentBlock = nextBlock(currentBlock, 1);
604 engine.keyState[SDL_SCANCODE_PERIOD] = 0;
607 if (engine.keyState[SDL_SCANCODE_COMMA])
612 currentBlock = nextBlock(currentBlock, -1);
622 engine.keyState[SDL_SCANCODE_COMMA] = 0;
625 Math::limitInt(¤tMonster, 0, MAX_ENEMIES - 1);
626 Math::limitInt(¤tItem, 0, MAX_ITEMS - 1);
628 if (defEnemy[currentMonster].sprite[0] == NULL)
631 if (defItem[currentItem].sprite[0] == NULL)
634 if (engine.keyState[SDL_SCANCODE_SPACE]) {showMap(&mapX, &mapY);}
636 if (engine.keyState[SDL_SCANCODE_S]) {saveMap(game.mapName); engine.keyState[SDL_SCANCODE_S] = 0;}
638 if (mapX < 0) mapX = 0;
639 if (mapY < 0) mapY = 0;
640 if (mapX > MAPWIDTH - 40) mapX = MAPWIDTH - 40;
641 if (mapY > MAPHEIGHT - 30) mapY = MAPHEIGHT - 30;
644 snprintf(string, sizeof string, "Index : %d:%d ; Screen %d:%d ; Tile %d", mapX + x, mapY + y, (mapX + x) * BRICKSIZE, (mapY + y) * BRICKSIZE, currentBlock);
645 else if (editing == 1)
646 snprintf(string, sizeof string, "Index : %d:%d ; Screen %d:%d ; %s", mapX + x, mapY + y, (mapX + x) * BRICKSIZE, (mapY + y) * BRICKSIZE, defEnemy[currentMonster].name);
647 else if (editing == 2)
648 snprintf(string, sizeof string, "Index : %d:%d ; Screen %d:%d ; %s", mapX + x, mapY + y, (mapX + x) * BRICKSIZE, (mapY + y) * BRICKSIZE, defItem[currentItem].name);
654 if (mapY < MAPHEIGHT - 30)
659 SDL_FillRect(graphics.screen, &r, graphics.black);
661 graphics.drawString(string, 320, r.y + 5, true, graphics.screen);
663 engine.delay(frameLimit);
664 frameLimit = SDL_GetTicks() + 16;
667 String *str = stringHead->next;
672 printf("Deleting %s", str->string);