Dark Overlord of Chaos Edition
Forum    Blog    FAQ    About    
Control Panel
Blog Entry
A Simple Game Map Editor
(jlucard, 20:44:33 - 26 Feb 2013 - / )

C#Perhaps this topic is not as exiting as a tutorial about building a game of some sort. However map and level editors are part of the process, at least for projects complex enough to justify them. A functional editor can save time and effort as well as allow non-programmers to help with level design. The process of building such a tool involves thinking about data structures, file formats, the art pipeline, and other boring, yet essential, aspects of the problem. As such there is a bit of learning to be done by undertaking such a task, assuming one does not forget that building a game (not an extra cool editor) is what the ultimately goal is. That said part of the editor problem, defining the data structures, is as good a start for making a game as anything, so perhaps this is a how to make a game tutorial after all.

A dark cold rainy evening this dark overlord decided to construct a simple map editor. Simple means that it has a limited feature set and a less than perfect GUI. It is however functional and can indeed be used simply as a tool for designing levels for games. That said, building a generic editor that will do for all games is rather problematic, if at all possible. Clearly some assumptions and restrictions are needed. Those are that the editor will used for designing level for tile based games, where the tiles are perfectly square, of equal size and conveniently arranged as a rectangular grid of columns and rows. It is also assumed that the earth is flat, meaning that the maps produced are two dimensional areas in terms of actor movements. Despite those restrictions this design can still be used for designing a wide variety of games such as maze games, turret games, RTS, RPG, etc.

At this point I should point out that many authors argue that building an editor using the game engine is a good thing. For all I know this might be a good approach for big companies with lots of money and manpower. However the truth is level editors do not have to be made using the same engine and/or even the same programming language as the game itself. When developing games as a hobby on the little spare time you have shortcuts are good. If you can get away with using an editor (or similar app) made for another purpose by another developer, do so. If using this editor save you time even better – it means I have achieved something here. The fact C# and windows forms were used for implementing this simple editor example does not matter. Code written in other programming languages could be used to load map files (I kept the format as simple as possible) made with this tool. Even better it could be used for designing levels for 3D as well as 2D games as, after all, 3D tiles can be rendered from the top.

To make a map for a tile based game we need three basic data structures – tiles, tile sets and (predictably enough) maps. The most basic of the three is tiles. The main advantage of tiles is that they can be combined in different ways to create new maps. As such they allow defining massive worlds, procedurally generated content, and encouraging content contributions by the user community. The main disadvantage is that making them is a tedious process especially since they need to match seamlessly. In its simplest form a tile corresponds to a single movement position on the map (actor can step on it, or not). However the smaller the tiles get the more tedious it gets to make them and construct the maps later. Even worst, artists simply hate working on a small canvas as it somehow limits their artistic flare. Finally in some graphics engines displaying a lot of small graphic artefacts is slower than displaying fewer larger ones. Some sort of balance needs to be achieved. Tiles have to be small enough to be reusable and big enough to satisfy the needs of the project and the artist. As such for a fairly generic editor (such as the one discussed here) the functionality of adding a mask (movement grid) to each tile is needed. In the editor example all tiles have a square movement grid (mask) associated with them. To keep things simple this have to be of the same size for all the tiles. In the example following the grid is of size 3x3.

Tile mask for road segment

In the figure above a 3x3 mask is used for the road tile shown. Clearly a mask with a higher resolution – i.e. 5x5 could allow a more precise match between the road area and the movement area as defined by the mask (assume 0 is no go and 1 is go). Different numbers can be used to indicate movement speed – i.e. 3 could had been used for the middle of the road while 1 for the edges, with 0 still been the no move area. Ultimately how these numbers will be interpreted depends on how you choose to interpret them in your code and what sort of game you are building.

The next structure to be put in place is that of a tile set. Loading all tiles into an array allows access to them by simply using an index number – the code does exactly that, with the array of tiles been stored into an array of tiles defined within the tile set class. The tiles contained in a tile set can simply be stored in a text file, along with their map related properties such as the movement mask for each one of them. Text files are sometimes something to be avoided as anyone can actually edit them. This is also one of their advantages as modifying games and producing additional content is a favourite pastime for some people in the gaming community. In any case using text files to store the data structures makes it easier to reverse engineer the file format and load the map data created by this tool into other applications, thus making it a bit easier to use it for games created using different programming languages.

Loading a tile set

The above figure show a tile set loaded into the editor. Each tile filename is followed by diameter of the square matrix (3 in this case) and the values for each of the nine (3x3) tile mask locations. Note that the mask size doesn’t have to be 3, but in the current editor version it has to be the same number for all the tiles in the tile set. Another feature of the tile set loader is that it reserves the tile in position zero as the no-tile tile. The tiles of the above example are therefore stored in an array of size 7, with position 0 being a no-tile tile and positions 1-6 holding the 6 tiles defined in this tile set. This decision was made to allow for gaps in the map, something that might be desirable for some games.

Using an array as the means for constructing the tile set is convenient. It means that the actual map can be constructed as a two dimensional array of integers, each of which is a tile id linking the particular map location to a specific tile of the tile set. That leaves one problem to tackle; tile rotations. In some cases drawing different tiles for different rotations might be the preferred approach (i.e. whenever tiles are drawn shaded by a light source somewhere). In many cases this is not an issue so having a way to rotate existing tiles could be useful. To achieve this end an extra value needs to be stored for each map location – the rotation angle (or rotation position). There are a number of ways to achieve that. This dark overlord chose to do so by using the parallel array approach – constructing a second two dimensional array of exactly the same size as the first to store the rotations corresponding to each map position. The map rotation array is also an array of integers (I dislike floats) where every map location can be assigned a rotation position value of 0-3, where 0 means a angle of 0*90=0, 1 an angle of 1*90=90, 2 an angle of 2*90=180 and 3 an angle of 3*90=270. A few additional methods for rotating tile mask are needed to make this work. The existence of two arrays (map and rotation) has implication as to how such a data structure could be saved to disk in an easily readable text form. The dark lord of chaos did not like the idea of having to use two numbers per tile. As such that cool guy decided to save the map as an array of floats, with the number before the dot identifying the tile, and the number after the dot identifying the rotation position. So for instance number 3.1 means show tile 3 rotated by 1*90 degrees. The following screenshot shows a map file in this text form.

A map file

The is one more thing missing from our abstract definition of the map idea. A way of actually using the data stored there in a game. In a game you do not want to do any of those lengthy rotations every time you display a tile. Similarly, when you need to decide where actors can or cannot go, you do not need the extra complexity imposed by our map, tile set, tile hierarchy. What you need is the important data – where can you or can’t move, in a usable form. In other words we need to match the map locations and rotations to the tile masks, process the information there and store somewhere in a convenient form before the game main loop kicks in. One solution is creating a movement mask for the entire map during initialisation. This is basically yet another two dimensional array, though bigger than the map itself as it also includes the tile masks appropriately rotated. The size of that array for a map of size (8, 6) with tiles that have a tile mask of size (3, 3) would be (8*3, 6*3) = (24, 18). For the map example above, with the tile set defined previously this array would look like this:

A mask for an entire map is just another array of integers

This should be enough for simple games that do not require complex AI. At the very least such a data structure could be used at least for deciding where the main character – the hero – can and can’t go.

The source code for the application attached to this post is split into two main parts – the first part defines the base map class and deals with building the concept of a tile map (what a map is, how it relates to a tile and how on earth do you load one from the disk). The second file simply contains the base class expanded so that the capability to display the map in a picture box on a form could be added. Clearly the general idea is that this part can be easily replaced by another one, thus easily changing how displaying the map is to be accomplished. I will not discuss this. As such tjis is a rather one sided discussion of the problem – an entire post talking about data representation and the rationale behind it. Yes, displaying graphics is important but simply not what I wanted to discuss. There are many graphics tutorials out there, yet relatively few posts about discussing games from a data representation and structure point of view, thus my insistence to talk about that instead. Nevertheless as the editor does actually does display and edit maps it should not be difficult to see how this is accomplished by studying/reading the source code attached.

Display/edit map screenshot

Hopefully some people will find some of this discussion, or even the editor and the source code provided useful. I did try to put some commends explaining how the code works though I can’t guarantee there are no bugs (I meant features). If you use it for a game do post a link in the forum somewhere – it will do wonders for my motivation to write more posts. Also tell you friends what a great site this is.

Note the .net 4.0 is required to run the application:
Map Editor Executable
Source code

P.S. The example tile set included is simply awful. If anyone want to donate a free tile set (preferably one that is less crap) for use by the GD Chaos community and overlords it would be great. The forces of darkness and chaos need you.

jlucard's picture
23:06:01 - 05 Mar 2013
Login or register 

I discovered an unplanned feature of the editor. If you try to minimise it while on the map display tab the program conviniently crashes. It should be fairly easy to fix but I have no time to look at this now.

Chain smoking makes you thin

Links to external sites
Who's online
In the last 15 minutes, no users have been active.
There are 32 registered users in total.
Most users ever online was 1083 on 02:39:16 - 10 Jun 2012
The art for this website is a copyright © of dark overlord jlucard.
Website powered by Drupal
This website is powered by Drupal