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
)
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
++)
45 r
.w
= r
.h
= BRICKSIZE
- 1;
47 tile
= map
.data
[x
+ mapX
][y
+ mapY
];
49 if (tile
== MAP_WATERANIM
)
51 tile
= graphics
.getWaterAnim();
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;
76 graphics
.updateScreen();
79 if (engine
.keyState
[SDLK_SPACE
])
82 for (int x
= 0 ; x
< MAPWIDTH
; x
++)
84 for (int y
= 0 ; y
< MAPHEIGHT
; y
++)
86 switch (map
.data
[x
][y
])
89 graphics
.putPixel(x
, y
, 9, graphics
.screen
);
92 graphics
.putPixel(x
, y
,graphics
.blue
, graphics
.screen
);
95 graphics
.putPixel(x
, y
, graphics
.green
, graphics
.screen
);
98 graphics
.putPixel(x
, y
, graphics
.red
, graphics
.screen
);
101 graphics
.putPixel(x
, y
, graphics
.white
, graphics
.screen
);
109 if (engine
.keyState
[SDLK_LEFT
])
112 if (engine
.keyState
[SDLK_RIGHT
])
115 if (engine
.keyState
[SDLK_UP
])
118 if (engine
.keyState
[SDLK_DOWN
])
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
);
133 engine
.keyState
[SDLK_SPACE
] = 0;
136 int nextBlock(int current
, int dir
)
138 if ((current
+ dir
) > 255)
141 if ((current
+ dir
) < 0)
144 int wanted
= current
;
150 if (wanted
< 0) return current
;
151 if (wanted
> 255) return current
;
153 if (graphics
.tile
[wanted
])
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
);
181 if ((absX
< (graphics
.width
+ 160)) && (absY
< (graphics
.height
+ 120)))
183 graphics
.blit(enemy
->getFaceImage(), x
, y
, graphics
.screen
, false);
186 if ((!(enemy
->flags
& ENT_WEIGHTLESS
)) && (!(enemy
->flags
& ENT_FLIES
)) && (!(enemy
->flags
& ENT_SWIMS
)))
187 enemy
->applyGravity();
192 void deleteEnemy(int x
, int y
)
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
);
216 void saveMap(char *name
)
218 Entity
*enemy
= (Entity
*)map
.enemyList
.getHead();
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
] << " ";
232 str
= stringHead
->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
);
257 for (int y
= 0 ; y
< 300 ; y
++)
259 is
.ignore(102400, '\n');
264 is
.getline(string
, 1022);
265 for (int i
= 0; i
< 1024; i
++)
273 printf("Read: %s", string
);
275 if (strstr(string
, "@EOF@"))
278 if (!strstr(string
, " ENEMY \""))
281 strcpy(str
->string
, string
);
282 stringTail
->next
= 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
] << " ";
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
))
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;
377 if (map
.data
[x
][y
] == 0)
379 map
.data
[x
][y
] = block
;
392 if (map
.data
[left
][y
] == 0)
394 map
.data
[left
][y
] = block
;
405 if (right
>= MAPWIDTH
)
407 right
= MAPWIDTH
- 1;
411 if (map
.data
[right
][y
] == 0)
413 map
.data
[right
][y
] = block
;
420 if ((!moveLeft
) && (!moveRight
))
428 int main(int argc
, char *argv
[])
432 printf("Usage: mapeditor <filename>\n\n");
442 if (!PhysFS::instance
->FileExists(argv
[1]))
445 game
.setMapName(argv
[1]);
451 int mapX
, mapY
, allowMove
, x
, y
;
452 mapX
= mapY
= allowMove
= x
= y
= 0;
455 int currentMonster
= 0;
457 int currentBlock
= 1;
465 unsigned int frameLimit
= SDL_GetTicks() + 16;
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
);
493 x
= engine
.getMouseX();
494 y
= engine
.getMouseY();
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
;
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;
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;
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
);
540 if (allowMove
< 1) 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
])
568 currentBlock
= nextBlock(currentBlock
, 1);
578 engine
.keyState
[SDLK_PERIOD
] = 0;
581 if (engine
.keyState
[SDLK_COMMA
])
586 currentBlock
= nextBlock(currentBlock
, -1);
596 engine
.keyState
[SDLK_COMMA
] = 0;
599 Math::limitInt(¤tMonster
, 0, MAX_ENEMIES
- 1);
600 Math::limitInt(¤tItem
, 0, MAX_ITEMS
- 1);
602 if (defEnemy
[currentMonster
].sprite
[0] == NULL
)
605 if (defItem
[currentItem
].sprite
[0] == NULL
)
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;
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
);
626 r
.w
= graphics
.width
;
629 if (mapY
< MAPHEIGHT
- 30)
630 r
.y
= graphics
.height
- 20;
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
;
647 printf("Deleting %s", str
->string
);