Page 1 of 3

Building level editors

Posted: Thu Mar 26, 2009 2:53 am
by CC Ricers
I've already made a few basic 2D games before but crazy as it seems I've never created a fully specialized level editor for any of my games. It's because most of the games I made were puzzles or scrolling shooters with basic backgrounds, and didn't really require any complex level work. I've also done some overhead 2D sprite tests (such as what you see in RPGs) but in any case they are just custom text files that get loaded by the game.

So I'd like to know how some of you start your approach with making a level editor. Do you start by planning out what the how "level files" will be formatted? How about the interface? Is it any better using a customized GUI that is part of the rendered graphics versus the Windows way of adding menus and form elements?

Re: Building level editors

Posted: Thu Mar 26, 2009 5:32 am
by programmerinprogress
well, I guess it depends on what you're trying to achieve.

The first editor I built, used to work off absolute co-ordinates (i.e. you could place objects in the level, free of any grid systems), I used to write my files thusly

map1.txt

Code: Select all

10,10,5,5, BALL 
24,43,88,98,PLATFORM
etc...
but, that gets a bit cumbersome, and it's a bit difficult to manage in comparison to a tile-based map file.

I started using tile-based map files when lusikkamage did those allegro tutorials, they're much easier to manage than writing out co-ordinates and widths etc.

The idea of a Tile-Based map, is to load up a specific amount of tiles, in the correct locations on the map.

So what you do is write a series of number codes, one after another (it usually helps if you write them into the map in a way which resembles the map your trying to create, i.e. put as many codes going accross the file as there are horizontal tiles, and then put the next line onto the next line)

the numbers in the number codes represent the tile you want to display on the map, usually you can use this number as a multiple of the tile size to set a clip location on your sprite.

Heres an example of how a tile-based map might look

Code: Select all

Tilemap.txt 

0001 0001 0002 0001 0003 0000
0001 0002 0003 0001 0001 0001
0002 0001 0005 0003 0002 0003 
This map would represent a 6x3 map on the screen

The editor itself, would need to be able to write this format, and the game would have to be able to read it, it's that simple!

I hope this helped ;)

Re: Building level editors

Posted: Thu Mar 26, 2009 6:47 am
by kostiak2
The game I'm working on uses a similar format:

Code: Select all

<image>
filename.png|x|y|h|w
...
<map>
00 00 00 00 00
00 00 01 00 00
00 01 01 01 00
02 02 02 02 02
This way, im loading an image file, then selecting what area i want to make a tile of (useful for sprite sheets), then the numbers represent the "tiles" ive loaded.. 00 represents empty space, and 01 represents the first image and so on..

for example:

Code: Select all

<image>
grass.png|0|32|32|32
<map>
00 00 00 00
00 00 00 00
01 01 01 01
That will make:
Image

Right now I'm editing the files manualy, but that is the basis of my editor..

Re: Building level editors

Posted: Thu Mar 26, 2009 8:40 am
by MarauderIIC
CC Ricers wrote:So I'd like to know how some of you start your approach with making a level editor. Do you start by planning out what the how "level files" will be formatted? How about the interface? Is it any better using a customized GUI that is part of the rendered graphics versus the Windows way of adding menus and form elements?
Usually my level editors are dependent on the engine. By the time I get started on a level editor, my engine loads the levels in a certain format. If this needs to change, it changes in the engine then in the editor. And honestly I never really did any deep planning on level files -- just some rough idea that I then design my engine to load.

As for GUI, the only level editor of mine that had any real progress was entirely text-based. But it was a text-based game. The editor was built into the game and if you had the right permissions you could invoke it from the game's prompt. Instead of typing, for instance, "look", I typed "edit" and then it presented the editor menu. Since it was an internet game it just re-output everything every time you went through the menus (as opposed to a clear screen / re-output). It was possible to jump to a certain subsystem or edit a certain NPC or item or whatnot without going through the main editor menu. For instance, if there was an NPC in room #4, I would teleport myself to room #4 (just "go 4") and "look" to see what all there was. If it presented me with

"[ EXITS ]
ROOM TITLE
ROOM DESC
Some item is here.
Bob the Builder is here.
Your mom is here.
Megaman is here.
Some player is here."

I could either "edit npc 2" or "edit npc mom" and it would bring up the NPC editor menu with that NPC loaded so I could edit its stats, description, shortname ("Your mom"), longname (also "Your mom" in this case). I could also "edit npc" which would bring up a numeric npc selection menu for that room (with npc listing for the zone as a sub-option), in case I had trouble finding the keyword for some reason (say if the names were accidentally blank). Also, from any room, I could "edit vnum 4" to bring up the editor for room 4 in the current zone I was in (which has the NPC editor as a menu option, along with change room exits, change room title, change desc, and so on). I could do something like "edit 2-4" to edit room 4 in zone 2. "Edit zone 2" from any zone to bring up the zone editor menu, etc. To make a new room off of a room, I would go to the room and then "edit exit N" and select "new room" from that menu (I could also assign it to an existing vnum). To make a new room that's not connected to anything, just "edit vnum new" or "edit vnum (some vnum that's not taken)" and then save it (no save == no new room). So quick access to subsystems and locations as well as instantaneous changes was a major design point. You might keep this in mind when designing a level editor :)

Oh, I love talking about that. I miss it [HD failure] :(

Re: Building level editors

Posted: Thu Mar 26, 2009 8:32 pm
by CC Ricers
Thanks for your input, kostiak2 and programmerinprogress, but I already know the ideas behind writing out tile maps with text editors. I am more interested in how to automate the process of making tile maps by taking a graphical approach to building levels, and not typing in text with something like Notepad.

MarauderIIC, that's some real helpful information. I guess it does make sense to have your editor use the same engine as your game. In that case should there be a parallel in development for both the game and the editor? In other words, keep the code updates persistent with the engine so that your editor doesn't suddenly stop working for your game. Do you have your editor share some of the source code with the game? Since I have a game state manager already set up, I was thinking that I can have it two states in the same program so switching between "edit" mode and "play" mode a breeze.

Re: Building level editors

Posted: Fri Mar 27, 2009 8:16 am
by programmerinprogress
CC Ricers wrote:Thanks for your input, kostiak2 and programmerinprogress, but I already know the ideas behind writing out tile maps with text editors. I am more interested in how to automate the process of making tile maps by taking a graphical approach to building levels, and not typing in text with something like Notepad.
You missed the point I was trying to make... My point was that you CAN automate this process using a level editor.

I treat games as map readers and map editors as Readers and Writers.

I tend to create an array, or some other type of container, to store the map references when the map is first loaded, then I use my editor to change those numbers, and tell the program to save the new map to the map file (truncating it's previous contents)

If memory serves me correctly, I tend to paste my screen (in the editor) with SDL rects, and check for collisions and mouse clicks, if there are any clicks, the system change the correspondant value of the tile in the array, and makes updates to the file (you are free of course, to wait till the user wants to save the map file, or close the app, if you don't want to immediately save the file).

I hope this answered the question a little better.

Re: Building level editors

Posted: Fri Mar 27, 2009 5:10 pm
by MarauderIIC
CC Ricers wrote:MarauderIIC, that's some real helpful information. I guess it does make sense to have your editor use the same engine as your game.
Yes, but it's not required, of course. Many editors are separate apps when it's more convenient.
In that case should there be a parallel in development for both the game and the editor? In other words, keep the code updates persistent with the engine so that your editor doesn't suddenly stop working for your game. Do you have your editor share some of the source code with the game?
Well, if your editor uses the same engine, it's in the same project. So you push a button to switch to edit mode while playing. It just reuses like, Map::load(), but you have to add Map::save(). I think that answers both questions and clarifies your one statement in there, right? :)
Since I have a game state manager already set up, I was thinking that I can have it two states in the same program so switching between "edit" mode and "play" mode a breeze.
Uh huh. Something like,

Code: Select all

case PLAY:
player.getInput();
player.processInput();
level.update();
level.draw();
break;

case EDIT:
player.getEditInput();
player.processEditInput();
level.update();
level.draw();
break;
I have getEditInput() and processEditInput() as two separate functions because otherwise you'd just have a huge if block inside of one function, and since you know what the state is before you process the input, you don't have to have the huge if.

Re: Building level editors

Posted: Sat Mar 28, 2009 3:34 pm
by CC Ricers
programmerinprogress wrote: You missed the point I was trying to make... My point was that you CAN automate this process using a level editor.

I treat games as map readers and map editors as Readers and Writers.

I tend to create an array, or some other type of container, to store the map references when the map is first loaded, then I use my editor to change those numbers, and tell the program to save the new map to the map file (truncating it's previous contents)

If memory serves me correctly, I tend to paste my screen (in the editor) with SDL rects, and check for collisions and mouse clicks, if there are any clicks, the system change the correspondant value of the tile in the array, and makes updates to the file (you are free of course, to wait till the user wants to save the map file, or close the app, if you don't want to immediately save the file).

I hope this answered the question a little better.
That helps a lot. Just making it check for input and add the appropriate data to your data structures stored on the heap, and when you use the save command write that data to a file. I guess the trickiest part is figuring out the best data structures for your levels/maps. Right now I'm trying to code a good enough reader so it can throw in everything in my scene in one go, and prevent it for crashing in case something is missing or invalid data is being entered. I have basic timer functions down pat so an auto-save feature would be nice for such a case.
MarauderIIC wrote:Well, if your editor uses the same engine, it's in the same project. So you push a button to switch to edit mode while playing. It just reuses like, Map::load(), but you have to add Map::save(). I think that answers both questions and clarifies your one statement in there, right? :)
That sounds like the sensible thing to do. I'll have to learn how to set up multiple projects in one solution with in Visual Studio.

Re: Building level editors

Posted: Sun Mar 29, 2009 11:16 am
by eatcomics
MarauderIIC wrote:
CC Ricers wrote:So I'd like to know how some of you start your approach with making a level editor. Do you start by planning out what the how "level files" will be formatted? How about the interface? Is it any better using a customized GUI that is part of the rendered graphics versus the Windows way of adding menus and form elements?
Usually my level editors are dependent on the engine. By the time I get started on a level editor, my engine loads the levels in a certain format. If this needs to change, it changes in the engine then in the editor. And honestly I never really did any deep planning on level files -- just some rough idea that I then design my engine to load.

As for GUI, the only level editor of mine that had any real progress was entirely text-based. But it was a text-based game. The editor was built into the game and if you had the right permissions you could invoke it from the game's prompt. Instead of typing, for instance, "look", I typed "edit" and then it presented the editor menu. Since it was an internet game it just re-output everything every time you went through the menus (as opposed to a clear screen / re-output). It was possible to jump to a certain subsystem or edit a certain NPC or item or whatnot without going through the main editor menu. For instance, if there was an NPC in room #4, I would teleport myself to room #4 (just "go 4") and "look" to see what all there was. If it presented me with

"[ EXITS ]
ROOM TITLE
ROOM DESC
Some item is here.
Bob the Builder is here.
Your mom is here.
Megaman is here.
Some player is here."

I could either "edit npc 2" or "edit npc mom" and it would bring up the NPC editor menu with that NPC loaded so I could edit its stats, description, shortname ("Your mom"), longname (also "Your mom" in this case). I could also "edit npc" which would bring up a numeric npc selection menu for that room (with npc listing for the zone as a sub-option), in case I had trouble finding the keyword for some reason (say if the names were accidentally blank). Also, from any room, I could "edit vnum 4" to bring up the editor for room 4 in the current zone I was in (which has the NPC editor as a menu option, along with change room exits, change room title, change desc, and so on). I could do something like "edit 2-4" to edit room 4 in zone 2. "Edit zone 2" from any zone to bring up the zone editor menu, etc. To make a new room off of a room, I would go to the room and then "edit exit N" and select "new room" from that menu (I could also assign it to an existing vnum). To make a new room that's not connected to anything, just "edit vnum new" or "edit vnum (some vnum that's not taken)" and then save it (no save == no new room). So quick access to subsystems and locations as well as instantaneous changes was a major design point. You might keep this in mind when designing a level editor :)

Oh, I love talking about that. I miss it [HD failure] :(
Yeah I remember reading about that and really wanting to play it... Then I found out you were irresponsible and didn't back it up... I almost cried... well not really... oh and btw I don't back up my code that often either... :lol:

Re: Building level editors

Posted: Wed Apr 01, 2009 6:19 pm
by thejahooli
eatcomics wrote:Yeah I remember reading about that and really wanting to play it... Then I found out you were irresponsible and didn't back it up... I almost cried... well not really... oh and btw I don't back up my code that often either... :lol:
Same really. But I've never really made anything worth backing up.

Re: Building level editors

Posted: Thu Apr 02, 2009 7:09 am
by ismetteren
I am also thinking about making a level editor, but i am not sure how to make the code that can parse the txt file, into something i can use in my game. Right now my code looks like this:

Code: Select all

void Stage::load() {
	if(mapPath != "" && solidPath != "" && tileSheetPath != "") {
		bool done1, done2;
		done1 = false;
		done2 = false;

		ifstream in;
		in.open(mapPath.c_str());

		int i = 0;
		while(!done1) {
			int j = 0;
			vector<Tile> vec;
			done2 = false;
			while(!done2) {
				char* c;
				int k;

				in.getline(c, 2, 's');

				if(*c == '\n') {
					done2 = true;
					break;
				}
				if(*c == 'x') {
					done1 = true;
					done2 = true;
					break;
				}

				k = atoi(c);
				Tile t;
				t.setX(k*32);
				vec.push_back(t);

				j++;
			}
			if(done1 == false) {
				map.push_back(vec);
			}
			i++;
		}
This looks like an ugly hack to me, but i have no idea how i else could do it.

And btw, the files it is loading is formattet like this:

Code: Select all

4s4s4s4s4s4s4s4s4s4s4s4s4s4s4s
s4s4s4s4s4s4s4s4s4s4s5s5s4s4s4s
s1s1s1s1s1s1s4s4s1s5s5s5s1s1s1s
s0s0s0s0s0s0s5s5s0s0s0s0s0s0s0s
s0s0s0s0s0s0s3s2s0s0s0s0s0s0s0s
sxs
i could have used ' ' instead of 's' but since there has to be spaces at the end of every line, it could be a little confusing if i used ' '

Re: Building level editors

Posted: Thu Apr 02, 2009 7:43 am
by MarauderIIC

Code: Select all

void Stage::load() {
    if (mapPath == "" || solidPath == "" || tileSheetPath == "")
        return;

    ifstream in(mapPath.c_str());
    if (!in) {
        cerr << "Could not open file " << mapPath << endl;
        return;
    }

    string tileX;
    //If you use dynamic allocation in your vectors, this can be very pretty. I'd recommend it so that you don't have to make a copy of the tile, too :)
    #ifdef OKAY_ILL_USE_DYNAMIC_ALLOCATION
    vector<Tile*> row;
    while (in) {
        for (getline(in, tileX, 's'); tileX != "x" && tileX != "\n"; getline(in, tileX, 's'))
            row.push_back(new Tile(atoi(tileX.c_str()) * 32)); //(1) (1.1)
        if (tileX != "x") //(2)
            map.push_back(row); //(3)
    }
    #else //---------------------------------------
    vector<Tile> row;
    while ... {
        for ... {
            Tile t(atoi(tileX.c_str()) * 32);
            row.push_back(t);
        }
        ...
    }
    #endif //---------------------------------------
}
(1) : I'm not sure why you multiply by 32. What happens if we have 1*32 in the same row? They overwrite each other?
(1.1) : If you have an 'x' and a 'tile type' this for loop can still be one line by using substr in combination with find & rfind, but it'd be more efficient if it weren't coded as such :)
(2) : There are a few different ways to eliminate this condition. A priming read is one. But this should work okay.
(3) : This will push empty rows

Where there's a constructor built like

Code: Select all

Tile(int xCoord) : setX(xCoord) {}
That should work, right?

Re: Building level editors

Posted: Thu Apr 02, 2009 9:11 am
by ismetteren
MarauderIIC wrote:

Code: Select all

void Stage::load() {
(1) : I'm not sure why you multiply by 32. What happens if we have 1*32 in the same row? They overwrite each other?
[/quote]

The number int the file is the tile number to use. The x position in the tile, determines what part of the tilesheet this tile is. So if the tile number is 3, i will multiply it by 32 to get the x position that tells me from where in the tilesheet i should blit, when i want to draw it.

The position in map(a vector of vectors of tiles vector<vector<Tile> >) decides where the tile should be drawn. Is that also a bad way of doing it?

Re: Building level editors

Posted: Thu Apr 02, 2009 9:21 am
by Vortex
i dont think someone have linked this already but lazyfoo have a great tutorial on how to approach an leveleditor
http://lazyfoo.net/articles/article09/index.php

Re: Building level editors

Posted: Thu Apr 02, 2009 9:32 am
by MarauderIIC
ismetteren wrote:
MarauderIIC wrote:

Code: Select all

void Stage::load() {
(1) : I'm not sure why you multiply by 32. What happens if we have 1*32 in the same row? They overwrite each other?
[/quote]

The number int the file is the tile number to use. The x position in the tile, determines what part of the tilesheet this tile is. So if the tile number is 3, i will multiply it by 32 to get the x position that tells me from where in the tilesheet i should blit, when i want to draw it.

The position in map(a vector of vectors of tiles vector<vector<Tile> >) decides where the tile should be drawn. Is that also a bad way of doing it?[/quote]I see. That's fine. I was thinking setX was setting the x position in the level. Of course not since you're using a 2D vector, so that was my bad, ha.