contact contact devblog goodies ourgames



Everybody Needs an Editor

When you are making a game at some point you should design maps and levels the player will play on. There are many possibilities to do this, but the most convenient is with the use of some kind of editor.

Let us say, we decided we will not hardcode levels into the game code but instead, use different files describing our levels. We need to create and modify such files, but what software shall we use for that? There are many choices from Notepad to 3dMax and different exporters, but the most suitable is probably an editor solely dedicated for this task.

Why to Use an Editor?

In the beginning of the development of Fortix II we used Notepad and hardcoded many things into the game. As the game escalated in complexity and number of levels, a dire need arose to have a much more convenient way to manage our maps. Since our build process is fully automated, (e.g.: creating objects from textures) it would have been nice to have something similar for the levels as well. Level files do not only contain the backgrounds of the actual level and objects scattered around, but other properties like the scripts assigned to the level or the carefully calculated duration of the game play as well.

Another good reason to have an editor was to see immediately how a map would work. You just have to put a tower here, drag some monster there and hit the play button and voila, you can already try the newly generated map. It is very important in rapid prototyping and development. We do not need to build anything or start a different application. As a matter of fact, we do not even need to save the map; the level designer can try his/her idea right away.

During the development it was also important to make the application easy to use. At some point we would like to release the editor to the community so everyone could create his/her own maps and play them or other peoples map creating a competition to have the most fun and cunning maps.

These were the main reasons and goals of our editor. But how was the life cycle of it?

Design and Implementation

Once upon a time on a sunny summer morning a little team started to create an editor to their game engine. The first thing to implement was an empty window that later can be filled with content and functionality. The content was given: a game, with levels in it. But, what functionality does some self-respecting editor need?

Basic Functionalities

First of all we need to manipulate the objects: change their position, orientation, scale or just select them. Other obvious functionalities are opening and saving the levels. If we have a level, we need to put new objects onto it, so we need to be able to add new objects to the map or remove them. Another very important part regarding a user friendly interface was to be able to correct the mistakes easily. Imagine having a large group of objects selected then a miss-click destroys all of this selection. But even a simple changing of mind about moving an object could be very annoying if we cannot undo that last action.

This made it clear: we need an undo/redo system. For that every manipulation of the object should be treated like and action, put in an action queue so we know the history of the objects. Now with this knowledge in our hand it is easy to restore a previous state of the level. Thus during the implementation we had to work with separate actions: select action, rotate action, delete action, etc.

Problems and Issues

The concept was fine and we liked the idea a lot. But, then came the implementation and the unforeseen difficulties. While the actions worked well by themselves, the “undo” and “redo” needed some further thought. For obvious reasons it is very effective to have the same function to do the “redo” and the actual action as well. The code will be easier to understand and we will have fewer functions in our class. Thus during the implementation of the actions we had to keep in mind that the “do” and “redo” should be the same (if possible) and the “undo” should be also easy to implement. For that we needed to store the optimal data about our level. If we know the original states of the objects we operate on and the new state resulted by the action we can effectively implement the undo and redo actions. During the execution of an action we have to save the state of our scene two times. First we save the initial data like selection state, instance names and IDs and later when we have done our transformation but the whole action has not been finished we save the states again. While the object transformations were fairly easy to implement with these guidelines in our mind, a new problem arose. Inserting and deleting an object.

If you think this seems easy to implement and won’t cause too many problems, then you are quite wrong. Imagine having your action queue, every action storing the undo/redo data of the object and the next action is a delete. Ok, we deleted some of the objects. What could be wrong?! Well, let us undo this action. Okay, it is pretty easy, we just insert a same instance of the object to the same location, restore the orientation and scale. Here we are and the system is still consistent. Well, the truth is that it is not. If we had pressed that undo again and we wanted to undo the previous action (let us say a selection) the program would crash. The reason is simple: while the instance itself was created and restored it had a new pointer and the former pointers in the action queue to this instance got invalid. This means if we insert or delete an object we have to update the pointers to this object in every action in the whole action queue. Later we found out that it is better not to store the pointers of the objects, but their so called object-ID instead. Restoring an object means the same object-ID, so all we need is to ask our level class for an object with the given ID. The invalid reference issue was dealt with.

Introduction of the Graphs

Another interesting issue during the making of the editor is the graphs. Since in Fortix II there are waters, swamps, walls and enemies patrolling given paths, it was an obvious choice to use graphs for these purposes. Putting the graphs into the editor opened up a whole new set of problems.

In-game the graphs are invisible, but we needed some kind of representation for them in the Editor. We used boxes as graph nodes and simple lines with little arrows as the directed edges (vectors) between the nodes. Now we had objects to work with. We could select the graph nodes, move them, rotate them and we saw the graph transforming.

The next issue was the undo/redo data. We needed to extend these since the editor did not know the phenomena graph links. These links had to be stored somewhere too. After a decent code refactoring we added these data to the undo/redo data as well plus we achieved a 10 – 15% decrement in the size of the code.

The last problem we had to face was merging and splitting graphs. You can create new graphs and add new nodes to them all right; you can even create links between two nodes, but what if you link two nodes from distinguished graphs? We need to unite them. This involves the copy of a whole graph including nodes and links between, into the other graph. When the copy is done we have to delete the first one. Splitting graph is the other way around. When you remove the last node holding the graph together it will fall into parts, but not necessarily 2. This means the creation of new graphs and sorting the remaining nodes and links into these new graphs.

The Future

We have been using and updating the Editor for a year now, it is gets better and better every day, and we have some big plans on the way. We would like to give it a nice user interface with buttons and menus. A property window is very much needed in order to manually set the transform matrix, name or other properties of an object as well.

Not having a UI might seem not too user-friendly, but we had good reasons to start this way. Without it, the editor reached its first usable form much sooner. Instead of the usual UI, we currently have a console where we can display different outputs, like the help with the layout of the control or the action currently being carried out. So, omitting the UI for the first version of the editor was actually a conscious decision.

The editor is evolving day by day, getting new features and buttons and functionality. We hope that soon the community will be able to use it to create their own levels.

 The Editor as it Currently Stands

 

Scaling, color changes, path setting and more features to come

Find the differences on the levels modified by the editor.

 

The Console

A typical console output of the Editor.

 

-Peter Minarik