PDA

View Full Version : questions about a map editor



leniz
28-05-2007, 12:10 PM
Hi. Me again,
Since I got my sprite working, I thought I need a map editor to test my sprite on some different terrain. So I started making a little map editor for my self and I encountered a few problems:
:arrow: How to save my tiles to array and export them to file?
:arrow: How to make some kind of undo or deletion tool?
Some kind of help would be much apreciated :D

Best regards, leniz

FNX
28-05-2007, 12:24 PM
:arrow: Why don't you use an already ready one? :D

http://tilestudio.sourceforge.net/

leniz
28-05-2007, 12:44 PM
I tried Mappy, but it can't make the files I need. I also searched for others but none of them seem to meet my requirements. What I need is a simple map drawing utility that can save all those '0' and '1' and other chars to a simple *.txt or other file. And to tell the truth, it would be nice to work with my own made tool. :D

Legolas
28-05-2007, 01:06 PM
Oh, I'm making my tilemap editor too :)
In my map class I use a filestream for load and save purposes. You will need to create your own file format, where you will store all map infos. A simpler approach could be using a text file to store your data.


// saving function
var
check, mapVer: array[0..2] of char;
...
f := TFileStream.Create(filename, fmCreate);
try
f.Seek(0, soFromBeginning);

check := 'emg'; // For control check when load the map
mapVer := '001';// Version number

F.Write(check, sizeof(check)); // I'm writing control check chars
F.Write(mapVer, sizeof(mapVer)); // version number
F.Write(mapName, sizeof(mapName)); // map name: string[255]
F.Write(mapDesc, sizeof(mapDesc)); //map description: string[4000]
F.Write(tileSet, sizeof(tileSet)); // tileset file name: string[255]
F.Write(TileSize, SizeOf(integer)); // tile size in pixel (eg. 16): integer;
F.Write(HorizTiles, SizeOf(integer)); //map width in tiles: integer
F.Write(VertTiles, SizeOf(integer)); //map height in tiles: integer
F.Write(LayerCount, SizeOf(integer)); //num of layers: integer

for a := 0 to LayerCount - 1 do
begin
F.Write(Layer[a].Name, SizeOf(Layer[a].name));
for y := 0 to VertTiles - 1 do
for x := 0 to HorizTiles - 1 do
begin
F.Write(Layer[a].Tiles[x, y].ImgIndex, SizeOf(integer));
F.Write(Layer[a].Tiles[x, y].collision, SizeOf(integer));
end;
end;
f.Seek(0, soFromEnd);
Result := true;
finally
f.Free;
end;
...

// Loading
f := TFileStream.Create(filename, fmOpenRead);
try
f.Read(check, SizeOf(check));
if check <> 'emg' then
begin
MessageDlg('Invalid .emg file.', mtError, [mbOK], 0);
exit;
end;

f.Read(mapVer, SizeOf(mapVer));
f.Read(mapName, sizeof(mapName));
f.Read(mapDesc, sizeof(mapDesc));
f.Read(tileSet, sizeof(tileSet));
f.Read(TileSize, SizeOf(integer));
f.Read(HorizTiles, SizeOf(integer));
f.Read(VertTiles, SizeOf(integer));
F.Read(LayerCount, SizeOf(integer));

SetLength(Layer, LayerCount);
for i := 0 to LayerCount - 1 do
begin
SetLength(Layer[i].tiles, HorizTiles, VertTiles);
end;

for a := 0 to LayerCount - 1 do
begin
f.Read(Layer[a].name, SizeOf(Layer[a].name));
for y := 0 to VertTiles - 1 do
for x := 0 to HorizTiles - 1 do
begin
f.Read(Layer[a].Tiles[x, y].ImgIndex, SizeOf(integer));
f.Read(Layer[a].Tiles[x, y].collision, SizeOf(integer));
end;
end;
f.Seek(0, soFromEnd);
Result := true;
finally
f.Free;
end;


Well, something like that. You will need some adjustments, of course :)


About undo, I have an Undo record like that:


TUndoRecord = record
posX, posY: Integer;
Layer: Integer;
Tile: Integer;
Collision: Integer;
end;
PUndoRecord = ^TUndoRecord;


and a TList where I store the state of the tile I will change. In order to undo changes, all you need is to get the last item in TList, restore its values and remove it from TList.
Hope it helps ;)

AthenaOfDelphi
28-05-2007, 02:28 PM
You may also want to check out this thread (http://www.pascalgamedevelopment.com/viewtopic.php?t=3997) which presents a set of objects that can be used as the basis for a tiled map... its based on the objects presented in this article (http://www.pascalgamedevelopment.com/viewarticle.php?a=68&p=1#article) which covers versioned data storage (as a means of illustrating the use of 'methodAddress').

leniz
28-05-2007, 02:51 PM
Legolas:
Well that seems clear enough.. or not. And since you are creating the same thing, I'm eager to ask you:
How are you drawing your tiles on the map?
Because the longer I think, the more I understand that my way is very unversatile.

Legolas
28-05-2007, 03:51 PM
Legolas:
Well that seems clear enough.. or not. And since you are creating the same thing, I'm eager to ask you:
How are you drawing your tiles on the map?
Because the longer I think, the more I understand that my way is very unversatile.

By looping from lower layer to higher, then tile by tile, of course :)
If you mean what I'm using for rendering, then in my map editor I use unDelphiX and in my engine OpenGL, though in an older version I used DirectX9 :)

leniz
28-05-2007, 03:57 PM
I meant when you are drawing your map with mouse in your map editor :wink:

Legolas
28-05-2007, 04:31 PM
Well, I handle onMouseDown, onMouseMove and onMouseUp events (in my case on a DXDraw component). It's matter of converting pixel based coordinates to map based coordinates, then write to the map the index of your selected tile (in my case there is a DXImageList with all tiles). For example:


procedure TForm1.DXDraw1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: integer);
var
TileX, TileY: integer;
begin
TileX := X div (myMap.TileSize);
TileY := Y div (myMap.TileSize);
if button = mbLeft then
// curlayer is the index of the current layer
// TileSelected is the tile I want to draw
begin
// handle Undo here
myMap.Layer[curlayer].Tiles[TileX, TileY].TileIndex := TileSelected;
end;
end;

leniz
28-05-2007, 04:58 PM
Looks similar to mine, but mine is without all that fancy 'undo' and 'curlayer' stuff :D
You know, I tried to do that saving part something like yours, but all I get from the output file is a bunch (~2.7mb to be exact) of crap... I can't seem to get the hang of that array to textfile gig... Dang, being a newbie realy annoys me :D

wodzu
29-05-2007, 07:15 AM
Hello ;)

I am also working on an editor ;) My saved map with dimensions 100x100 and 100 objects on it has ~37 kb in size. I am using binary files to store data. They are fast and easy, have you tried them? They are similar in usage to the streams showed by Legolas. Also to achieve a small map in size is to store in it only the things which you really need.
For example if you would like to save to your map 100 Objects which are different only in the terms of position, do not save all their properties. Save an ID which represents such object and its position.

jasonf
29-05-2007, 10:57 AM
I know this will probably sound odd, but I would advise that you don't spend too much time on your editor and forget to write your game.. or build an editor which becomes a feature creep monster and takes time away from developing your game. Time and Creative energy are a premium, don't waste them.

I spent a long time working on an editor for a game I was writing called Anomalous, in the end, I hadn't considered some things and it became too much work to fix.. the editor was cool though, it used the game engine itself to render tiles and sprites, saved files in XML and was quite powerful, I'd got a list of additional features I was going to add but I got overwhelmed by the size of the monster I'd created. Also it was very specific and could not be used on any other games so was in effect, a complete waste of time. I should have used something else.

I would consider using an existing editor these days, if I could get away with using TileStudio, or Mappy, then I would.. even if it meant writing a conversion utility to convert between their format and my own... I'm sure even things like Milkshape or Xara could be used as a level editor if they were used in the right way and files were exported into a format which could be processed.

Re-inventing the wheel can be fun and sometimes seems like it's the only way, but at the end of the day, you've just made a wheel, very similar to lots of other wheels.. the rest of the car is still to be built.