Name: | Battalion |
---|---|
Version: | 1.4b |
Authors: | Andy Johnson |
License: | Free, but with a couple of restrictions |
Operating System: | Several Unixes, Macintosh and Windows |
Website: | http://evlweb.eecs.uic.edu/aej/AndyBattalion.html |
"Monsters, explosions, senseless destruction. You've seen the movies, you know what to do." (Battalion web site)
Giant monster movies come alive in the virtual world of Battalion. The player takes control of a rampaging monster destroying a city. As the devastation mounts, the military launches numerous attacks against the beast. Eventually even the ferocious Googelon falters under the combined attacks.
As noted above the Battalion version used for this article is listed as 1.4b, but the web site lists 1.5 for the Macintosh and 1.5beta2 for Windows. The site isn't clear about the differences between all the various versions. The source for any of the 1.5 versions doesn't appear to be available. A slightly reorganized web site would be beneficial. Ideally, the web site should have a changelog and a single source package of the latest version. If possible all binaries should be compiled from the original source package. I grabbed both the original 1.4 source and the Linux 1.4 version. The source for 1.5 is apparently available by request and simply hasn't been put on the web site yet. The only changes were for the Mac version.
Since I recently upgraded to a 3dfx video card, I downloaded the 3dfx patch as well. I had a shaky start with a beta Mesa version, but everything seems alright under Mesa 3.2. There is a problem with using a 3dfx card though. The monster movement can be controlled by the mouse or keyboard. For the mouse movement, if the pointer is above the center of the screen, the monster moves forward. Backward movement is caused by moving the pointer below the screen center. Being to the right or left of the center turns in the appropriate direction. Unfortunately the full screen mode of Mesa for 3dfx does not draw the mouse pointer.
I initially intended to look into this issue and discuss some of the challenges in designing a 3D game. Perhaps even add an option for drawing the pointer to solve the 3dfx problem. The Muses had a different plan in mind, however.
For a long time I've derided sound in computer games. But there is a noticeably missing quality when playing a game without sound and music. A small sample of the theme music can quickly spark memories of old adventures. Even the simple beeps and gleeps of yesterday adds to the atmosphere.
The Linux version of Battalion uses the SoundIt library 0.03 by Brad Pitzel for sound support. The SoundIt library was apparently modified slightly by Sash Chukov when he added sound support to Battalion. The library only supports mono 8-bit samples, but for the simple sound effects and music of Battalion it works. In order to mix and play sounds simultaneously, the library spawns a separate process, a technique criticized on the LGDC mailing list.
There are several reasons for the criticism. The simplest to understand
is that interprocess communications isn't instantaneous and may lead to some
delay between firing a rocket and hearing the whoosh. Instead it has been
suggested that a ProcessSound
function be called in heavily
trafficated areas of code. I figured implementing such a system for
Battalion would make an interesting patch. Rather than reimplement a
low-level library, I downloaded the latest version of SDL and SDL_mixer.
Since I hadn't heard complaints about the various Loki ports, I expected to find the technique suggested on the LGDC mailing list. Surprisingly SDL uses a multi-threaded approach, where a separate thread handles sound not an entire process. Using a thread reduces or eliminates some of the problems of a separate process but remains suboptimal on a uniprocessor machine.
So why bother implementing it? SDL works on numerous platforms. Using
SDL many of the ifdef
s in audio.c could be eliminated.
Currently Battalion uses different audio formats, depending on the system.
Since SDL can read wav files on any system there is no need to maintain
raw files for Linux, au files for Solaris, etc.
Following good design principles, the sound interface is relatively
simple and avoids revealing hardware implementation to the programmer.
However, there is one minor kink in the system. When the program initially
starts initSounds
clears all the global variables relating
to sound. Later, checkSound
determines if the system has
sound and loads the audio files if needed. Since nothing uses the
sound variables between initialization and checking for sound, there is
no reason to separate the two functions. In addition even before calling
the initSounds
function, the global noSound
variable is set to false and functions to turn off the sound and music
are executed. The possible incorrect setting of noSound
is
not modified until checkSound
is called. Overall the sound
initialization seem illogical and awkward.
Luckily the rest of the major audio functions are more straightforward.
During the main game loop, flushSounds
updates information
about the currently playing sounds. At various other points the program
may call doSound
or soundKiller
. The former
starts playing the appropriate sound file. The latter stops playing a
sound.
There are two other functions to be aware of when creating a new sound
implementation, InitAudio
and OutAudio
. During
sound initialization you have two steps: hardware initialization and the
loading of sound files. Reading and processing each audio file requires
the same steps so InitAudio
packages it all up. The other
function is called by doSound
to actually play the sound.
In theory the bookkeeping performed by doSound
could then
be system independent. In practice the bookkeeping didn't match up too
well.
Coding the SDL implementation was relatively simple.
I mainly copied the Linux SoundIt implementation and modified the functions
to use the SDL_mixer equivalent. The only exception being
soundKiller
which does nothing in the Linux SoundIt version.
Instead the type of sound playing on each channel is recorded when the
sound is started. That way the appropriate channels can be halted.
Since the sound may have completed, the halt may be unnecessary but may
be more efficient than ensuring the playing channel information is correct.
In addition to the patch, you will
need the wav files from the windows binaries to use the SDL implementation.
Unfortunately I did end up referring to the source code of the SDL_mixer library during the porting. As this is my first attempt at sound programming, I was confused by the usage of the term "channel." When initializing the mixer library, one the arguments is the number of channels. One channel means mono sound and two allows stereo output. When you want to play a sound, once again channel is an argument. Channel in this case refers to the mixing channels which default to eight and are entirely separate from the audio channels. Since SDL_mixer currently lacks documentation, the only choice for new users is the source.
So how is the rest of the source code? The majority of the source is found in a small number of files. Most files define numerous global variables. There are plenty of comments explaining the various sections so it is fairly easy to understand what is going on. Unfortunately battalion.c seems to have a rather haphazard placement of functions which makes finding a particular function more difficult.
While exploring the source to Battalion, I was surprised to find the monster models hard coded in the source. My initial thought was that this may have been done to simplify animation. However, Andy Johnson informed me that the restriction was due to the hardware limitations of 1995 low-end SGIs. Much of the code is still influenced by this legacy. Updating the code would be a large undertaking but would lead to much more flexible game.