Programming Linux Games: A Book Review
Although Linux receives a lot of praise as a rock-solid server and, recently, as an up-and-coming desktop, games have never been its strong suit. Sure, we all have our favorite diversions; I've spent more than my share of hours playing NetHack. But quite a few Linux users still keep a Windows partition around just to play games.
The efforts of groups like Loki Software have greatly improved things by porting many popular Windows games to Linux. Others projects, such as the Mandrake Linux Gaming Edition, allow you to play Windows games without having to reboot your computer. But let's face it, few (if any) quality games are initially released for Linux.
Marketing issues aside, there are no technical reason for this lack of Linux games--the tools are out there. Which brings us to this book.
As the title suggests, Programming Linux Games discusses some of the major APIs you can use to create professional-quality games for Linux. The book seems to be geared as an introductory text. As the author writes, "I assume you know the basics of working with Linux; if you know enough to start X, open a terminal, copy files around, and fire up a text editor, you're good to go. I also assume that you have a reasonable grasp of the C programming language."
I'd also recommend having at least a cursory familiarity with the make utility and the build process. These topics are covered, but very briefly. And this could be a real source of frustration to programmers coming from other operating systems.
As far as appearances, well, they often say first impressions are the most important. Unfortunately, this book is unlikely to raise any eyebrows.
The layout is typical of No Starch Press books. If you've seen one, you've seen them all: black and white, mostly text, with a clean (some might say stark) appearance. No trendy layouts. No sidebars or elaborate graphical elements. As the No Starch motto says, "More Stuff, Less Fluff."
In general, I am a big proponent of simplicity, but I feel the No Starch approach goes a little too far. The simplicity actually makes this book harder to use. A prime example is chapter tabs. Dark rectangles printed along the outer edge of the page, chapter tabs are used typically in almost all computer books and for good reason. They add simple visual cues that make it much easier to scan quickly for information. I tend to use indexes the same way I use my VCR's instruction manual--only when all else fails. Tabs are a feature I greatly appreciate, but one that is missing in this book.
Similarly, the book provides references to the important structures and functions discussed in the text, but this material is mixed into the chapter--usually just after the function is introduced. While this makes the book very easy to understand when reading from cover to cover, it is not the best design for a reference book. Things are just a little too hard to find.
It would be nice if the reference material was all grouped together (or at least grouped at the end of each chapter). An ideal compromise might involve repeating the reference material in an appendix--but then the book would be bigger and probably more expensive.
The content can be divided into roughly three sections: the introduction, the APIs and the wrap-up. The introduction (roughly a sixth of the book) is a quick survey of game archetypes, tools of the trade and useful APIs.
The chapter on games compares and discusses a variety of game types, including simulations, first-person shooters, real-time strategy, turn-based strategy, role-playing, puzzles and MUDs.
The tools chapter introduces vi, Emacs and NEdit and discusses the basics of using make, static libraries and shared libraries. Debugging with gdb, ddd and bug tracking is also covered. Other topics include version control using CVS and other useful utilities, including grep, diff and patch. Oddly, Autoconf is not discussed here but is briefly mentioned at the end of the book.
The introductory material finishes off with a quick survey of the APIs that game programmers may find useful. This is sort of an everything-but-the-kitchen-sink list, with a brief description of each item. Only a few of the APIs mentioned here are actually discussed again in later chapters.
While it doesn't tell you how to use the APIs, I believe the introduction is one of the most useful chapters in the book. One of the largest challenges I've found when working with Linux is just finding the right tools for the job. Given the sheer breadth of applications, APIs and libraries out there, finding the best tool is often much more difficult than learning to use it.
The bulk of the book is dedicated to explaining a few APIs in more detail, covering SDL, audio programming, network gaming, scripting engines and even gaming for the Linux framebuffer. Obviously, they don't give you a complete description of the APIs, but the information provided is more than enough to get you started.
The first API chapter (filling almost a quarter of the book) describes SDL and covers a variety of topics, includes drawing pixels, blitting bitmaps, processing user input, multithreaded programming and SDL audio programming. It also introduces a sample game that is slowly built throughout the book, Penguin Warrior.
While primarily focused on 2-D gaming, this chapter provides a brief overview of using OpenGL with SDL. If you plan on doing any real 3D programming, however, you will want to consult additional SDL and OpenGL resources.
Linux audio is somewhat schizophrenic, and the chapter on audio programming mirrors that. It discusses the differences and uses of OSS, ALSA and ESD, including an introduction to all three APIs and a sample sound program demonstrating their uses. The audio chapter ends with a description of OpenAL and a discussion of playing background music using Ogg Vorbis files.
While informative, this chapter seemed to be somewhat overkill. As the authors pointed out, using a high-level library like SDL or OpenAL is probably better than messing with OSS, ALSA or ESD directly. So I'm left feeling that the space they used to describe these APIs could have been better spent covering some of the many topics that did no make it into the book.
The chapter on game scripting, on the other hand, was one of the most interesting. This is a subject that most game programming books do not even touch. As such, it is one of the real gems of Programming Linux Games. It is disappointing, however, the discussion focuses on Tcl, a decision that seems to be based on the library's ease of use, rather than its appropriateness as a game scripting engine.
Given that games generally need as much (or more) performance as you can pack in, I really wish they had picked a scripting engine based on performance. I also wish they had included a comparison of the different scripting engines. Given the number available to a Linux game programmer, it would be nice to have some advice on how to chose between them.
Like almost every current book on game programming, this book contains the mandatory chapter on networked game programming. Here, this amounts to a basic description of socket programming, covering both TCP and UDP. If you've already read any other descriptions on socket programming, this chapter probably won't add anything new.
Finally the APIs end with a chapter on programming games for the framebuffer. This is a bit of a detour, kind of like visiting the worlds biggest ball of twine--odd but somehow fascinating.
The framebuffer is a kernel-based interface to video hardware. This chapter includes a discussion of the pros and cons of using the framebuffer, as well as how to set up the framebuffer, adjust the video mode and handle input.
Technology-wise, this felt like a step back in time. But as the authors said, "If you survived this chapter, you now know how to write games for the Linux framebuffer console, complete with fast video, keyboard and mouse processing. I still recommend SDL for most things, but it's fun to do things at a lower level from time to time."
With the APIs covered, the book ends with a short wrap-up, adding the last few touches to Penguin Warrior and discussing software distribution, including the differences between Linux distributions, the differences between Linux and FreeBSD and an overview of the various packaging systems. Autoconf is briefly introduced as a way to make projects portable, and the chapter gives a brief description of the Filesystem Hierarchy Standard.
Most of the distribution information was pretty plain; however, the description of Loki's setup program stands out. I didn't realize it was released under the GPL, and I had never considered using it before.
As you can see, this book covers a lot of ground, but it doesn't cover everything. As the authors say, "This book is not about game design, the mathematics of 3D graphics, or advanced OpenGL programming. These topics are best left to books of their own; I could not hope to do them justice here."
Since very little OpenGL is directly related to Linux, discussions are limited to using SDL as a GLUT replacement to setup OpenGL. Actual OpenGL programming is not covered.
The book also does not contain a CD-ROM. This was a deliberate decision--the authors intended to make a web site for the book, containing links to all the necessary libraries. While the preface claims that this site can be reached through either www.lokigames.com or www.nostarch, I was not able to find a link on the Loki site. The only link I found on the No Starch site was a download link for a tarball containing the complete source code for the samples. Ironically, my copy of Konqueror did not like this link and gave me fits when I first tried to download it. There was no web page of links to the libraries; however, the needed URLs are listed throughout the book, so that is not really necessary.
Programming Linux Games is well written, often amusing and never stuns the brain the way some computer books do. Hall and the Loki staff clearly know their stuff, and they have scattered great hints and tips throughout. For example, the description of the Bresenham algorithm is, by far, the cleanest and most comprehensible that I have ever seen. Likewise, I thought the suggestion to use POV-Ray to automatically create the needed graphics was incredibly useful. I'm sure you will find handfulls of your own helpful tidbits.
On the downside, this book is more a road map than a guidebook. While the title suggests that it will discuss programming Linux games, it really doesn't. Although it is a great introduction to many Linux technologies and provides a nice introduction to SDL and OpenAL, the book does not cover game design or how to create a game engine in anything but a very superficial way.
If you have experience programming games on other platforms, or if you are willing to read other books to fill in the gaps, then this is an excellent introduction to Linux gaming technologies. But it is just that--an introduction. After finishing the book, you still have a lot of homework to do before you can begin creating quality games.
Also, I was disappointed with Penguin Warrior. While it serves its basic purpose, providing a concrete example on using the APIs, it is a less than ideal sample. The authors admit that they created it while they wrote the book, without any formal design process. They even list a number of elements that should have been done differently: using C++ instead of C, using UDP-based networking, using a different scripting engine, creating a resource manager to handle the sounds and graphics and using Autoconf to manage the build tree.
All of which makes me wonder--why didn't they go back and fix it? I understand that samples need to be somewhat stripped down, but there's no excuse for publishing something you know is flawed. And if they didn't want to (or couldn't) change the book, they should at least provide an updated version of the sample source code.
I also feel the sample should have been expanded to include the creation of a quality (and reusable) game engine. Other books have managed to balance demonstrating both relevant APIs and quality game design. Had that been done here, the book would be great, not merely good.