Editor's Note: Earlier this month, Howard Wen examined Falcon's Eye in Falcon's Eye: the Making-Over of Nethack. We're proud to present an interview with Jaakko Peltonen, creator of Falcon's Eye, who discusses some of the technical and social challenges his project has faced.
O'Reilly Network: How has the isometric, third-person view you implemented for NetHack been generally received by players and, particularly, NetHack enthusiasts?
Jaakko Peltonen: I believe it has been received rather well. I've received hundreds of emails regarding Falcon's Eye. Several people have said they started or restarted playing NetHack after finding Falcon's Eye. Many new players seem to use Falcon's Eye.
NetHack enthusiasts have varied responses. One issue has been visibility -- people liked to see the entire level of the dungeon at once, while Falcon's Eye shows a scroll-able smaller area. I've tried to improve this by including a radar-like mini-map, a separate top-down map window, and high resolution support.
ORN: What are the graphics engine implementation details for such a project?
JP: In NetHack each dungeon level is a 2D plane, so full 3D isn't that useful for its gameplay. If the levels had elevation differences (rising and falling corridors/rooms) that affected combat, rolling boulders or the like, a 3D engine might be more useful.
At one point, I thought about making an interface with 3D models of each tile, a full 3D version of Falcon's Eye in a sense. This would be rather easy programming-wise, since only the actual tile drawing would change -- most other graphics and background logic would be the same. I intended to add artificial elevation differences, just to make the levels look more interesting. I decided against the 3D version, since I felt it would make the game confusing; tile-based movement and keyboard compatibility might suffer.
One advantage of full 3D models is easy animation: each animation frame is just a set of object-vertex positions. In most 2D games, frames are separate pictures, which takes more memory and disk space.
Falcon's Eye doesn't currently have animation, but lots of people have asked for it. I might add "static" animation like flickering torches, running fountains, creatures glancing around, etc. "Dynamic" animation like walking is more difficult for a number of reasons. First, to work well, it needs separate animations for each movement direction. Second, the interface then needs to find out what happened between turns. NetHack doesn't provide this by default. Neither is impossible to solve, but they do require more background logic for the interface.
ORN: It sounds like you created wrapper functions around DirectX and SDL. Since SDL itself on Windows is a thin wrapper around DirectX, is this the case?
JP: Falcon's Eye uses DirectX straight from the wrapper on Windows. SDL is only used for the Linux and BeOS ports. This avoids having a "wrapper of a wrapper."
Having a self-made wrapper -- instead of, for example, using SDL throughout -- is useful since Falcon's Eye can then also support platforms that SDL does not, like DOS. When the underlying API (such as DirectX or SDL) is well-designed, the wrapper doesn't need to do much -- at best it simply passes on its parameters -- so it doesn't slow down the game with much overhead. Also, if a future version of DirectX or SDL were to change the API to improve hardware support, I could simply change the contents of the self-made wrapper functions to match.
ORN: What are your experiences with cross-platform development with SDL?
JP: I found SDL quite easy to use. Its API is fairly similar to the wrappers I had written myself. So in many areas, it felt familiar to me already. The only feature I missed at first was MIDI music support. I solved that by using an external music player the user can configure. This turned out to be a good thing, since I could add support for other music file types in the same way.
Since I had already used similar APIs, I didn't perhaps learn as much as when I started GUI development earlier. I didn't look at SDL's implementation details behind the API. I'm sure I'd have much to learn there.
ORN: Any lessons learned from NetHack's portability? Its separation of display from game logic?
JP: That was certainly a major help here. Both the separation and the modularity were useful. NetHack only has a few files for the display functions of each interface, and its internal data representation is generally display-independent.
NetHack's portability across different computer systems -- UNIX, DOS, Linux, Windows, Amiga, Mac, different processor types, and so on -- is quite incredible. It goes beyond the display alone and includes considerations for things like file handling and compiler specifics. Although I don't intend to support Falcon's Eye across as wide a range of platforms, it does help me understand which kinds of platform-specific features and programming solutions to avoid.
ORN: What advice would you give to someone writing a GUI for a well-loved character-based application? (One can imagine the complexity of implementing gVim, for example.)
JP: One should first consider the goals of the GUI. In most cases, a GUI can provide more clarity or quicker ways to accomplish tasks. If the character-based application has clear problems with either of these, that's something the GUI should try to improve.
There are several routes for improving clarity. For example, character applications are usually oriented for a rather small display with few rows and columns. By contrast, many though not all GUI applications can assume there is a moderate amount of screen area available. Restructuring the display for more space can make it clearer. The GUI graphics also affect this; they can help associate related components, but too many graphical effects can make GUIs look cluttered.
Character applications are naturally restricted to character symbols, so they may need to draw complex structures (arrows, boxes, diagrams, buttons) with characters. A GUI can draw these in a more intuitive way. Also, GUI applications can use color or other highlighting where character applications need separate messages, capitals, etc., and can provide more feedback by tooltips, sub-windows or other means.
Regarding speed, in a highly evolved character application, the keyboard usage is probably already well optimized. Simply adding buttons for key presses won't make much difference. Instead, one should consider how the mouse can best be used in tandem with the keyboard. For example, character applications often have an "active area" for user input, with a command line or text menu, and the rest of the screen is for information only. This can make the active area feel cramped. In a GUI, the entire application area can accept user input.
Overall, the GUI should work in concert with the keyboard interface. Especially with widely used programs, users have learned how to use the character interface quickly, and changing this functionality probably hurts the overall speed and adds an unnecessary learning step. The GUI should instead provide alternatives. Some users may eventually use a combination midway between the old and new interfaces. Allowing this can sometimes mean making several different ways to do a task, which takes considerable work in both design and implementation, but I believe it is well worth the trouble.
ORN: How does having artistic skills, such as you clearly have, both help and complicate things when developing graphics and sound programs?
JP: One advantage is that I always consider both the presentation and its implementation together. I know what kinds of graphics and sound I can create, as well as how to solve some programming tasks. I can then design programs to get the best combined effect from these areas.
I often start out designing an interface simply by creating a mock-up image of how it should look. On the basis of the image, I can judge how the program logic should be arranged. What is the function hierarchy, which structures are fixed and which need to be modifiable, how does the program flow through the task? When the basic layout is fixed, I finalize the look of each component, often simultaneously with the code that uses it, which helps with testing.
If I started with code alone, I might stress "elegant" coding solutions, which can sometimes be cumbersome in practice: too simple hierarchies can lead to overly complex data representation and vice versa. Looking at the graphics gives me a user's perspective, which helps find the necessary programming compromises. On the other hand, knowing implementation details helps keep in mind what ideas are easy to realize, so that I don't draw interfaces too difficult to program.
This kind of development can sometimes mean I need to draw the interface graphics several times over if I do change the program structure. Also, sometimes I can spend too much time over graphics when I should concentrate on programming, design or sound; if one area lags behind others, I might not be able to effectively test them together.
Overall, though, I think there are more positive than negative effects from knowing these areas. It can also help with long development periods -- if I temporarily grow tired of drawing or sound design, I can switch to programming, and back again later.
Howard Wen is a freelance writer who has contributed frequently to O'Reilly Network and written for Salon.com, Playboy.com, and Wired, among others.
Return to the Linux DevCenter.
Copyright © 2009 O'Reilly Media, Inc.