I mentioned in my last blog entry that the main editing tool is an in-game console with commands for adding new objects and creating new maps. As my engine has evolved many features had become merged with the console that really should not have been, for example the actual logic of the console commands in many cases needed to be separate functions. With all of the unrelated logic in one place, adding new commands became increasingly difficult. To fix this problem, I refactored the console by moving these features into more appropriate modules, I also separated the console commands into there own classes. Now the console module is complete independent of the commands which it runs.
When I refactored the console I realized that I needed to redesign the settile hotkey. In my RPG engine, the map is represented by an array of tiles, the user can set the type of the tile their player is standing on by typing "settile <type>" into the console. Because this is such a common operation, it is not practical to make the user type this command in every time, so I had the console remember the last arguments passed to this command and then all the player would need to do was press the "w" key to execute the same command again. However, now I made the commands independent of the console I no longer wanted the console to be storing the arguments of a specific command. Well I was thinking about how to fix this I suddenly thought that it might be nice to have this hotkey feature for other commands or have hotkeys for different arguments. So I came up with a new console command that can assign any console command to any of the number keys. For example, "hotkey 1 settile;sand" sets the tile under the player to sand when the 1 key is pressed. Another advantage of this feature is that I can assign "sand" to the 1 key and "grass" to the 2 key, where before I would have to type in a console command every time I wanted to switch between the two tile types.
For my next feature I wanted to be able to write a list of console commands in an external file and then have them executed sequentially. When I refactored my console I realized that this would not be very difficult to add and would help easily accomplish what I had originally designed my engine to do, generate a large amount of content with minimal high level user input. One difficult I was confronted with was that loading maps took a couple milliseconds to load and scripts executed in a separate thread. I solved this by adding a command to tell them to wait a certain number of milliseconds to give the map a chance to load. Another problem was that because I am executing hundreds of commands at once I more frequently come across some of the race conditions that I had noticed occasionally in the past. While at the moment these race conditions seem an annoyance, I think of this as an opportunity to find and fix these serious bugs that would not have been possible with manual testing. I am excited about how quickly I was able to add console scripting and I believe it will be very useful going forward.
With the addition of console scripting I can now generate hundreds of maps and add doorways between them. I thought it would be interesting to visualize all of these maps and their connections, so I wrote a console command that would query the list of doors to identify the directed edges between the maps. The program then outputs a file with a list of these directed edges in a format that I can input into a graph making program called Graphviz. Well this graph is interesting to see now, it will be very useful for some of my planned features. One feature that will require a graph of directed edges is non-player character (NPC) path finding, eventually I want to program NPCs to walk between maps, and by analyzing graphs like this they will be able to identify the best path.
By improving the tools in these ways, along with some other minor improvements, I have greatly reduced the amount of work I need to do to create a map and can now focus on higher level design decisions. Well these tool improvements are very interesting, they are not the only new feature that I have implemented since February. In one of my next blog entries I will talk about some of the other new features. I am also hoping I will have time to upload another video to demonstrate some of these new features. In the meantime I am adding new feature to this project and the next big area I need to improve is NPC behavior and interaction. So stay tuned!
An example map graph generated using test data based on a popular classic RPG game. At this point all of the maps are empty, aside from doors (represented in the graph by directed edges) |
No comments:
Post a Comment