Doug Kavendek - Portfolio

Zomgrels

Zomgrels
Title Zomgrels
Started Spring 2007
Status Ongoing
Platforms Windows, Unix, others
Created For Personal
Source v0.015 (144 KB)
Executable v0.015 (Win32) (15.2 MB)
02.jpgOptions screen, with text input, sliders, checkboxes, and dropdown menus

It is perfectly acceptable (though poor form) to make a single-player game that just dumps you directly into the action upon starting the program. For multiplayer endeavors, this seems quite inadvisable, so in a burst of forward-thinking planning, I decided to create a thorough, configurable, and persistent user interface. My goal was to make something that can be used to easily create menus, accept all kinds of input, allow dynamic key bindings, and save all changes. This nearly complete overhaul of my framework and interface code is the result, code-named Zomgrels.

Of course, at first I had underestimated the requirements for such a system. I had no idea of the intricacies of accepting input from the user into text boxes without making any use of existing software. How do you limit input amounts? Should you limit it? What about selecting text, and cut/copy/pasting text? How should text scroll when it doesn't fit? I hadn't really expected to have to make so many human interface design decisions, and it only got more complicated when I added checkboxes, sliders, and selection/dropdown menus.

01.jpgThe main menu, with header image and command choices. Every image is a placeholder

My goal became to mimic the behavior that a typical user expects from a similar looking interface. For example, the user can either click and drag, or use shift and the arrow keys to select text -- and then can cut or copy or paste as they wish. Control-A selects all, and tab moves between menu elements. I also wanted to accommodate any sort of input, so the user can scroll through boxes either with arrow keys, page up/down, the mouse scroll wheel, or even joystick axes.

A secondary goal cropped up: menu elements should be easy to specify and position. My original plan used hard-coded function calls, but this was messy and difficult. I ended up creating a fairly simple text parsing system to create menu pages and define elements. Within it, a page can be defined, given a name, styled, given a background, and then have its elements positioned sequentially. Unless specified to be positioned absolutely, objects in the page conform to columns specified in the menu style, so subsequent elements are positioned with respect to preceding ones. Additionally, there are many optional parameters for menu elements which specify explicit attributes, to override either the global defaults or the local page styles. For example, the selection color can be left the default green for everything, but for a particular element you might need it to be purple. Or, more powerfully, you can even attach an image onto a text or command object.

14.pngThe console, showing past output and command matching for the current command's arguments

Almost everything is controlled with text files. Default and user settings are stored in game.cfg and user.cfg, respectively. Additional resolutions can be added to resolutions.dat, so any crazy monitor setup can be accommodated (though most normal users won't even have to think about this extra complexity). Any controls differing from the defaults are stored as a console script file controls.con, which is executed at the start of the program, along with autoexec.con, which can contain any special user-defined scripts. And of course, all of the game menus are defined in menus.dat.

The menu system relies heavily upon the console. Commands within a menu are defined as console scripts, which are sent to the console when the user activates them. Additionally, the console commands "menu_open" and "menu_close" control which menu pages are opened, and how they open (whether they are added to the menu page tree, or if they break off from it, and other options). Anything you can do with the console can be done with a menu element's "command" parameter. When using the console directly, it has the benefit of both command and argument matching, as well as providing feedback on input -- specify too few parameters and it tells you how many you need, as well as if a command has succeeded or failed.

03.jpgControls screen, with primary and secondary bindings for each action

There are many ways to output messages to the user. On a normal run, log.txt generates a basic list of events, while err.txt records various errors and warnings. There is a message structure that outputs sequential messages to the screen overlay, which fade over time -- these are logged in msg.txt. The announce structure outputs continually to a given line, based on the channel specified in its call -- the fps counter is one example of this. Stdout and stderr also are sometimes generated, for even lower level logging. Dialog boxes can also be spawned within the program, to provide warnings or ask for confirmation.

05.jpgQuit confirmation dialogue

In order to test whether the system really works well with a game inside it (and because it just seemed like it would be fun), I recreated Tetris within the framework. It turned out the be even easier than I had expected, requiring very little work apart from the basic game logic because all of the annoying parts of it, such as handling input, storing settings, and displaying overlays, had already been completed. On top of that, I figured it would be interesting to create a simple, greedy AI, and though it's far from perfect, it can play a remarkably good game.


15.pngTetris!
16.pngThe AI shows no mercy
12.jpgA sample infuriating error message
10.jpgKey binding overlay menu -- menus can be defined to either replace their parent menus or overlay them