\chapter{Mastering SDL}
\label{ch:masteringsdl}

\index{SDL!overview|(}Simple DirectMedia Layer (SDL) is a cross-platform multimedia library that has been used in countless free games and several commercial projects. SDL works with a platform's underlying multimedia capabilities to provide a consistent and open API across multiple operating systems. In this chapter we will tour the various facets of SDL with respect to Linux game programming.

SDL's full name, \emph{Simple DirectMedia Layer}, summarizes the design of the library. SDL is simple to learn and use: its API is well defined (if a bit sparsely documented in the recently added areas), uncluttered, and to the point. It provides direct access to the computer's multimedia capabilities where possible and does its best to compensate if the computer's underlying support is missing in some area. Finally, SDL is a thin and well-behaved layer of code rather than a subsuming beast. It is possible and often desirable to use individual components of SDL separately, and it is possible to integrate SDL into applications other than games to provide special multimedia capabilities. For instance, a game might use SDL for audio and some other toolkit for graphics, or an office suite might use SDL to display video clips. The most important use of SDL, though, is game programming.

\longpage
The SDL library consists of several sub-APIs, providing cross-platform support for video, audio, input handling, multithreading, OpenGL rendering contexts, and various other amenities. We'll begin our tour with graphics programming. Before we jump into the world of surfaces and pixels, however, let's take a look at the hardware that makes it all possible.
\index{SDL!overview|)}

\section{Computer Graphics Hardware}
\index{graphics hardware|(}
Every personal computer is equipped with a video controller of some sort. This set of chips is responsible for producing images on the screen, based on the data contained in a certain area of memory (the \index{framebuffer}\firstterm{framebuffer}). In addition to this basic drudgery, the video controller often assists software by providing hardware-accelerated drawing functions. Video controllers usually reside on replaceable \index{video card}\firstterm{video cards} that can be easily upgraded as video technology progresses.

Video cards contain a unit called a \index{CRTC}\firstterm{CRTC}, an acronym for \firstterm{cathode ray tube controller}. This device (either a separate chip or part of another chip) instructs the monitor to redraw its picture at regular intervals. The image on a computer screen is composed of horizontal lines on a fluorescent surface, and the monitor's hardware updates these from top to bottom. Each completed image is called a \index{refresh}\firstterm{refresh}. The CRTC instructs the monitor to perform a new refresh at least 60 times each second. The brief pause between refreshes is known as the \index{vertical retrace}\firstterm{vertical retrace}, because this is when the monitor's electron beam returns to the top of the screen. No matter how quickly the data in the framebuffer changes, the monitor is not updated until the next refresh. The video hardware's refresh rate is therefore of great interest to a game developer.

\label{pixels}
The image on a computer screen is divided into discrete colored areas called \index{pixels}\firstterm{pixels} (short for \firstterm{pictorial elements}). Each pixel can be individually controlled by the video card. The \index{resolution}\firstterm{resolution} of a display specifies the number of pixels across and down; for instance, a screen with a resolution of 640 by 480 is a matrix of 640 columns and 480 rows. The video card uses a device called a \index{RAMDAC}\firstterm{RAMDAC} (\firstterm{random access memory digital-analog converter}) to pump these individual pixels from the framebuffer memory to the monitor. Video card manufacturers like to brag about the speed of their RAMDAC components.

\index{graphics hardware!acceleration}
Since there are a lot of pixels on the screen (anywhere from 64,000 to more than a million), producing complete images can be an intensive process, especially if a program needs to change the entire contents of the screen several times every second. Video chip manufacturers have invested a large amount of research in this problem and have created video accelerator chips to help with this work. Video accelerators can speed up graphical applications (such as games) by performing time-consuming updates with dedicated hardware. For instance, video accelerators can often help out by performing high-speed copying between the framebuffer and other areas of memory. Computer memory is fast, but today's video games need every bit of performance they can get.
\index{graphics hardware|)}

\section{The Framebuffer}
\label{framebuffer}
\index{framebuffer|(}
The framebuffer is an area of memory that describes the image on the screen, with each on-screen pixel corresponding to one memory location. The exact format of the framebuffer is determined by the video chipset, but it is most commonly a simple array (this is known as a \index{framebuffer!linear}\firstterm{linear framebuffer}). To change the color of a pixel on the screen, a program must calculate the location of the pixel in the array (with the formula $width \times y + x$), determine the correct representation of the desired color, and store the color representation in the framebuffer. The video card then sends the new pixel color to the monitor during its next screen refresh.

% FIXME: does \dot work right?

Pixels are almost always represented by one- to four-byte values, but the exact format of these values depends on the current video mode. The following schemes are used to specify pixel colors in the framebuffer:
\index{framebuffer|)}

\label{displaymodes}
\index{display modes|(}
\index{video modes|see{display modes}}
\begin{bodylist}
\index{indexed (display mode)}
\item [Indexing] Pixel values are indices into a preset table of color values, which is called the \index{colormap}\firstterm{colormap} or \index{palette}\firstterm{palette}. Each entry in this table consists of a red, green, and blue intensity level. The video card converts the indices into actual color intensities (signals for the monitor's electron guns) as it goes. These video modes generally use one byte per pixel, allowing for a meager 256 colors on the screen at once. The palette can usually be changed at will (but updates to the palette will not show up until the next refresh). Clever programmers occasionally use the palette to implement animation tricks and special effects. Indexed modes offer extremely fast performance but relatively few simultaneous colors.

\index{hicolor (display mode)}
\item [Hicolor] Pixel values are 16 bits (2 bytes) each. These bits are divided into red, green, and blue fields. It is common for hicolor modes to allocate 5 bits to red, 6 bits to green, and 5 bits to blue, but you cannot assume that this will be the case. Hicolor offers excellent performance potential and a decent representation of the color spectrum, and it is frequently used for game programming. However, it lacks the color depth necessary for professional graphics. This is currently the most important pixel format for game programming. Hicolor is also known as \firstterm{High Color}, but most people use the shorter term.

\index{true color (display mode)}
\item [True Color] Pixel values are 24 bits each, allotting 1 byte to each color channel. True Color modes are extremely easy to program (since they do not require bit shifting or masking), but they tend to be rather slow due to the increased amount of video data. Some True Color modes use 32 bits for each pixel, simply wasting the 4th byte. This improves performance in many cases, because 32-bit processors are usually more efficient at accessing data aligned on 4-byte boundaries.

\index{direct color (display mode)}
\item [Direct Color] Pixel values are divided into three bit fields, each of which is an index into a palette for a particular color channel. That is, Direct Color provides a separate palette for red, green, and blue. This scheme combines the advantages of indexing with the excellent color depth of True Color. Direct Color is rarely used for game programming (it is mainly a feature of high-end graphics workstations) and is mentioned here only for the sake of completeness.
\end{bodylist}

Although the variety of video modes may appear to be a serious programming nightmare, many games simply pick one mode to support (such as hicolor), and inform the video card of that mode when they start. If a video card does not allow a certain mode, it is often possible to perform on-the-fly conversion between pixel formats with only a minor performance loss. It is sometimes possible to write programs in a depth-independent manner.
\index{display modes|)}

\section{The SDL Video API}
\label{sect:sdlsurfaces}
\index{SDL!video programming|(}
SDL uses structures called \index{SDL!surfaces!overview}\firstterm{surfaces} for manipulating graphical data. A surface is simply a block of memory for storing a rectangular region of pixels. You can think of a surface as a generic chunk of video data. Surfaces have widths, heights, and specific pixel formats, just as framebuffers do. In fact, SDL represents the video card's framebuffer as a special surface. The rectangular regions of data stored in surfaces are often called \index{bitmap}\firstterm{bitmaps} or \index{pixmap}\firstterm{pixmaps}.

The most important property of surfaces is that they can be copied onto each other very quickly. That is, one surface's pixels can be transferred to an identically sized rectangular area of another surface. This operation is called a \index{SDL!surfaces!blitting}\index{blitting}\firstterm{blit}, or \firstterm{block image transfer}. Blits are a fundamental part of game programming because they allow complete images to be composed out of predrawn graphics (generally created by artists with image-processing software). Since the framebuffer is a surface, entire images can be sent to the screen with a single blitting operation. SDL provides a function for performing fast blits between surfaces, and it can even convert between surfaces of different pixel formats on the fly.

Most games rely almost exclusively on surface blits for their drawing (as opposed to drawing with individual pixels). For example, consider the game \gametitle{Civilization: Call To Power} (which was ported to Linux using SDL). Other than the lines used to indicate paths and gridpoints, every character and building that you can see is stored in memory with surfaces, and they are drawn on the screen with blits. All of the game's artwork was created by artists and stored in files. The game assembles its screen images almost entirely out of these predrawn graphics.

We will now examine a series of SDL video-programming examples. It would be a good idea to compile and run each of these examples and to tweak them until you understand how they work. Don't worry about typing in all of the examples; they are available on the book's Web page. Throughout the rest of the chapter (and throughout chapters to come) we'll make note of important structures and functions with references like this:

\begin{apiref}
\apifunction{PrepNuke(kilotons, target)}
\apisynopsis{Sets up a tactical nuke and aims it at \code{target}.}
\apifirstparm{kilotons}{Power rating of the desired nuke.}
\apinextparm{target}{Target of the nuke. 0 picks a random destination. \emph{Be careful.}}
\apiendparms
\end{apiref}

Don't worry if you don't understand the relevance of a particular function or member of a structure at first; some are presented as a reference for advanced SDL users. Most of them should make sense by the end of the chapter.

\subsection{Setting Up the Display}
\index{SDL!basic usage|(}
Before we can begin writing to the framebuffer, we need to tell the video card what we expect of it. It needs to know the screen resolution we want, as well as the pixel format to expect in the framebuffer. SDL can handle this for us with the \codei{SDL\_SetVideoMode} function. The following example demonstrates how to set the display to a particular video mode and prepare the framebuffer for drawing:

\begin{codelisting}{initializing-sdl.c}{code:initializingsdl}
\begin{verbatim}
/* Example of initializing SDL. */

#include <SDL/SDL.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
    SDL_Surface *screen;

    /* Initialize SDL's video system and check for errors */
    if (SDL_Init(SDL_INIT_VIDEO) != 0) {
        printf("Unable to initialize SDL: %s\n", SDL_GetError());
        return 1;
    }

    /* Make sure SDL_Quit gets called when the program exits! */
    atexit(SDL_Quit);

    /* Attempt to set a 640x480 hicolor video mode */
    screen = SDL_SetVideoMode(640, 480, 16, SDL_FULLSCREEN);
    if (screen == NULL) {
        printf("Unable to set video mode: %s\n", SDL_GetError());
        return 1;
    }

    /* If we got this far, everything worked */
    printf("Success!\n");

    return 0;
}
\end{verbatim}
\end{codelisting}

This program includes the \filename{SDL.h} header file, in the \filename{SDL} subdirectory. This is the master header file for SDL; it should be included in all SDL applications. It also includes two standard headers, for the \code{printf} and \code{atexit} functions.

We begin by calling \codei{SDL\_Init} to initialize SDL. This function takes an ORed list of arguments to indicate which subsystems should be initialized; we are interested only in the video subsystem, so we pass \codei{SDL\_INIT\_VIDEO}. Unless an error occurs, this function should return zero to indicate success. We also use C's \code{atexit} facility to request that \codei{SDL\_Quit} be called before the program exits. This function makes sure that SDL shuts down properly.

\begin{apiref}
\indexc{SDL\_Init}
\apifunction{SDL\_Init(flags)}
\apisynopsis{Initializes one or more subsystems of SDL.}
\apireturns{Zero on success, a negative number on failure.}
\apifirstparm{flags}{Subsystems to initialize. This is an ORed list of flags. Possible flags are \codei{SDL\_INIT\_VIDEO} and \codei{SDL\_INIT\_AUDIO}, among others.}
\apiendparms
\end{apiref}

Next, we use the \code{SDL\_SetVideoMode} function to inform the display of our desired resolution and color depth. There is a catch here: SDL will try to set up the display as requested, but it might fail. If this happens, SDL won't tell us; instead it will emulate the requested mode internally. This is usually acceptable, since the emulation code is relatively fast and we would usually rather not deal with multiple modes ourselves. \code{SDL\_SetVideoMode} returns a pointer to the surface that represents the framebuffer. If something goes wrong, this function returns \code{NULL}.

\begin{apiref}
\indexc{SDL\_SetVideoMode}
\apifunction{SDL\_SetVideoMode(width, height, bpp, flags)}
\apisynopsis{Creates a window or initializes the video adapter to prepare for SDL video output.}
\apireturns{Pointer to a valid \code{SDL\_Surface} structure on success, \code{NULL} on failure.}
\apifirstparm{width}{Width ($x$-resolution) of the desired video mode.}
\apinextparm{height}{Height ($y$-resolution) of the desired video mode.}
\apinextparm{bpp}{Desired color depth. Likely values are 8, 15, 16, 24, or 32. 0 lets SDL pick any supported mode.}
\apinextparm{flags}{Mode flags. Possible values are \code{SDL\_FULLSCREEN} (requests a fullscreen video mode), \code{SDL\_DOUBLEBUF} (requests a double buffered video setup), \code{SDL\_HWSURFACE} (requests a hardware framebuffer for fast updates), \code{SDL\_OPENGL} (requests an OpenGL context), and others. We'll discuss most of these later.}
\apiendparms
\end{apiref}

Finally, we report success and exit. The C library calls \code{SDL\_Quit} automatically (since we registered it with \code{atexit}), and SDL returns the video display to its original mode.

\begin{apiref}
\indexc{SDL\_Quit}
\apifunction{SDL\_Quit()}
\apisynopsis{Shuts down SDL cleanly, regardless of its present state.}
\end{apiref}
\begin{apiref}
\apifunction{SDL\_QuitSubSystem()}
\apisynopsis{Shuts down a particular component of SDL, leaving the others untouched. It is safe to shut a subsystem down twice; SDL keeps track of its state internally.}
\apifirstparm{flags}{ORed bitmask of subsystems to shut down. These are the same flags you would pass to \code{SDL\_Init}. To shut down the audio subsystem without touching the video subsystem, you would use \code{SDL\_QuitSubSystem(SDL\_INIT\_AUDIO)}.}
\apiendparms
\end{apiref}

\index{SDL!compiling with|(}
Now that we've created an SDL application, we need to compile it. SDL applications are easy to compile; assuming a proper installation of SDL, they require just a few flags and libraries. The standard SDL distribution includes a program called \index{sdl-config utility}\cmdline{sdl-config} (similar to the \cmdline{gtk-config} and \cmdline{glib-config} scripts that ship with the GTK+ toolkit) for supplying the appropriate command-line arguments to gcc. The command \cmdline{sdl-config --cflags} produces a list of the options that should be passed to the compiler, and \cmdline{sdl-config --libs} produces a list of libraries that should be linked in. These options allow SDL applications to compile correctly regardless of the location or version of the library. The following command will correctly build an SDL application:

\begin{shell}
\tt{\$ gcc sdltest.c \verb|-|o sdltest \`{ }sdl\verb|-|config \verb|--|cflags \verb|--|libs\`{ }}
\end{shell}

Or, to separately compile and link multiple source files that use the SDL library,

% FIXME FIXME FIXME
% Typeset ` as a backtick

\begin{shell}
\tt{%
\$ gcc \verb|-|c file1.c \`{ }sdl\verb|-|config \verb|--|cflags\`{ }\\ %
\$ gcc \verb|-|c file2.c \`{ }sdl\verb|-|config \verb|--|cflags\`{ }\\ %
\$ gcc file1.o file2.o \verb|-|o mygame \`{ }sdl-config \verb|--|libs\`{ } %
}
\end{shell}

Note the use of backtick substitution (a standard shell feature) to insert the output of sdl-config into the command line. Of course, it is also possible to run \cmdline{sdl-config} yourself and insert its output into the command line by hand, but this would reduce the portability of your makefile. \cmdline{sdl-config} produces the following output on one particular Linux installation:

\begin{shell}
\begin{verbatim}
$ sdl-config --cflags
-I/usr/include/SDL -D_REENTRANT
$ sdl-config --libs
-L/usr/lib -lSDL -lpthread
\end{verbatim}
\end{shell}

\index{SDL!compiling with|)}
\index{SDL!basic usage|)}

\subsection{Direct Surface Drawing}
\index{SDL!direct drawing|(}
Putting data into an SDL surface is simple. Each \code{SDL\_Surface} structure contains a \code{pixels} member. This is a \code{void *} to the raw image, and we can write to it directly if we know the type of pixel that the surface is set up for. We must call the \codei{SDL\_LockSurface} function before accessing this data (because some surfaces reside in special memory areas and require special handling). When we are finished with the surface, we must call \codei{SDL\_UnlockSurface} to release it. The width and the height of the image are given by the \code{w} and \code{h} members of the structure, and the pixel format is specified by the \code{format} member (which is of type \codei{SDL\_PixelFormat}). SDL often emulates nonstandard screen resolutions with higher resolutions, and the \index{SDL!surfaces!pitch}\index{pitch|see{SDL, surfaces, pitch}}\code{pitch} member of the pixel format structure indicates the actual width of the framebuffer. You should always use \code{pitch} instead of \code{w} for calculating offsets into the \code{pixels} buffer, or else your application might not work on some configurations.

\begin{apiref}
\indexc{SDL\_Surface}
\structname{SDL\_Surface}
\structsynopsis{Represents a video surface.}
\structfirstmember{flags}{ORed bitmask of surface flags. For instance, the \code{SDL\_HWSURFACE} bit of \code{flags} will be set if this is a hardware (video memory) surface. \emph{Read-only.}}
\structnextmember{format}{Pointer to this surface's pixel format information (a \code{SDL\_PixelFormat} structure). \emph{Read-only.}}
\structnextmember{w}{Width of this surface (in pixels). \emph{Read-only.}}
\structnextmember{h}{Height of this surface (in pixels). \emph{Read-only.}}
\structnextmember{pitch}{Number of pixels per scanline in memory. This is often different from the surface's width -- beware! Always use \code{pitch} for pixel offset calculations. \emph{Read-only.}}
\structnextmember{pixels}{\code{void} pointer to the actual data that makes up this image. \emph{Read-write only after you call \code{SDL\_LockSurface}.}}
\structendmembers
\end{apiref}

\begin{apiref}
\indexc{SDL\_LockSurface}
\apifunction{SDL\_LockSurface(surf)}
\apisynopsis{``Locks'' a surface, making its pixels available for direct access. You can use \code{SDL\_MUSTLOCK(surf)} to determine whether a particular surface requires locking; some surfaces don't. Do not call \code{SDL\_BlitSurface} on a locked surface.}
\apireturns{Non-\code{NULL} on success, \code{NULL} on failure.}
\apifirstparm{surf}{Surface to lock.}
\apiendparms
\end{apiref} 

\begin{apiref}
\indexc{SDL\_UnlockSurface}
\apifunction{SDL\_UnlockSurface(surf)}
\apisynopsis{``Unlocks'' a surface. Use this as soon as you have finished drawing on a locked surface.}
\apifirstparm{surf}{Surface to unlock.}
\apiendparms
\end{apiref}

Our next example uses the SDL pixel format information to draw individual pixels on the screen. We have chosen to use a 16-bit (hicolor) mode for demonstration purposes, but other modes are equally simple to program. Bear in mind that plotting pixels in this way is invariably slow---don't even think of using this code for any substantial amount of drawing in a real program!

\begin{codelisting}{direct-pixel-drawing-sdl.c}{code:directpixeldrawingsdl}
\begin{verbatim}
/* Example of direct pixel access with SDL. */

#include <SDL/SDL.h>
#include <stdio.h>
#include <stdlib.h>

Uint16 CreateHicolorPixel(SDL_PixelFormat * fmt, Uint8 red,
                          Uint8 green, Uint8 blue)
{
    Uint16 value;

    /* This series of bit shifts uses the information from the
       SDL_Format structure to correctly compose a 16-bit pixel
       value from 8-bit red, green, and blue data. */
    value = ((red >> fmt->Rloss) << fmt->Rshift) +
            ((green >> fmt->Gloss) << fmt->Gshift) +
            ((blue >> fmt->Bloss) << fmt->Bshift);

    return value;
}

int main()
{
    SDL_Surface *screen;
    Uint16 *raw_pixels;
    int x, y;

    /* Initialize SDL's video system and check for errors. */
    if (SDL_Init(SDL_INIT_VIDEO) != 0) {
        printf("Unable to initialize SDL: %s\n", SDL_GetError());
        return 1;
    }

    /* Make sure SDL_Quit gets called when the program exits! */
    atexit(SDL_Quit);

    /* Attempt to set a 256x256 hicolor (16-bit) video mode.
       This will set some type of 16-bit mode, but we won't
       know which particular pixel format ahead of time. If
       the video card can't handle hicolor modes, SDL will
       emulate it. */
    screen = SDL_SetVideoMode(256, 256, 16, 0);
    if (screen == NULL) {
        printf("Unable to set video mode: %s\n", SDL_GetError());
        return 1;
    }

    /* Video memory can be strange, and it's sometimes necessary to
       "lock" it before it can be modified. SDL abstracts this with
       the SDL_LockSurface function. */
    SDL_LockSurface(screen);

    /* Get a pointer to the video surface's memory. */
    raw_pixels = (Uint16 *) screen->pixels;

    /* We can now safely write to the video surface. We'll draw a
       nice gradient pattern by varying our red and blue components
       along the X and Y axes. Notice the formula used to calculate
       the offset into the framebuffer for each pixel.
       (The pitch is the number of bytes per scanline in memory.) */
    for (x = 0; x < 256; x++) {
        for (y = 0; y < 256; y++) {
            Uint16 pixel_color;
            int offset;
            pixel_color = CreateHicolorPixel(screen->format,
                                             x, 0, y);
            offset = (screen->pitch / 2 * y + x);
            raw_pixels[offset] = pixel_color;
        }
    }

    /* We're finished drawing, so unlock the surface. */
    SDL_UnlockSurface(screen);

    /* Inform SDL that the screen has been changed. This is
       necessary because SDL's screen surface is not always the real
       framebuffer; it is sometimes emulated behind the scenes. */
    SDL_UpdateRect(screen, 0, 0, 0, 0);

    /* Pause for a few seconds as the viewer gasps in awe. */
    SDL_Delay(3000);

    return 0;
}
\end{verbatim}
\end{codelisting}

\index{SDL!pixel packing}The code's comments give the play-by-play, but a few points should be clarified. This program employs a very general routine for constructing hicolor pixel values; this routine will work with any hicolor format that SDL recognizes. Although we could write a separate (faster) routine for each possible hicolor data layout, doing so would require a lot of work and would only marginally improve performance. The 565 (5 red bits, 6 green bits, and 5 blue bits) pixel format is perhaps the most widely used format and could be reasonably optimized, but 556 and 555 are not uncommon. In addition, there is no guarantee that the bit fields will be in the red-green-blue order. Our \code{CreateHicolorPixel} routine solves this problem by referring to the data in the \code{SDL\_PixelFormat} structure. For instance, the routine uses the \code{Rloss} member of the structure to determine how many bits to drop from the 8-bit red component, and it then uses the \code{Rshift} member to determine where the red bits should be located within the 16-bit pixel value. For an interesting experiment, have the program print out these fields, and determine which particular hicolor layout your video card has given to SDL. My video card (a Matrox G400 under XFree86 3.3.6) happens to use the 565 format.

\newpage
\begin{apiref}
\indexc{SDL\_PixelFormat}
\structname{SDL\_PixelFormat}
\structsynopsis{Contains information about a surface's pixel composition.}
\structfirstmember{palette}{Pointer to this surface's palette (of type \code{SDL\_Palette}, if this is a paletted image.}
\structnextmember{BitsPerPixel}{Color depth of this surface. Possible values are 8, 15, 16, 24, or 32.}
\structnextmember{BytesPerPixel}{Number of bytes needed for each pixel. This is usually \code{BitsPerPixel} / 8, rounded up to the nearest integer.}
\structnextmember{Rloss}{Number of bits to remove from an 8-bit red color value in order for it to fit in the allotted space. For instance, a 565 video mode allows for 5 bits of red color data, so the \code{Rloss} would be 3. \code{SDL\_PixelFormat} also contains \code{Gloss}, \code{Bloss}, and \code{Aloss} members for the green, blue, and alpha channels.}
\structnextmember{Rshift}{Number of bits to shift the red value in order to position it in the correct bit field. There are similar \code{Gshift}, \code{Bshift}, and \code{Ashift} members.}
\structnextmember{Rmask}{Bitmask for extracting the red component from a pixel value. There are similar \code{Gmask}, \code{Bmask}, and \code{Amask} members.}
\structnextmember{colorkey}{Color value for colorkey blitting. Set this with \code{SDL\_SetColorKey}. More on colorkey blitting later.}
\structnextmember{alpha}{Transparency value for the surface associated with this \code{SDL\_PixelFormat} structure. Set this with \code{SDL\_SetAlpha}. More on alpha blitting later.}
\structendmembers
\end{apiref}

Another important issue involves the \codei{SDL\_UpdateRect} function. As we mentioned earlier, SDL sometimes emulates video modes if the video card is unable to provide a certain mode itself. If the video card does not support a requested 24-bit mode, for instance, SDL might select a 16-bit mode instead and return a fake framebuffer set up for 24-bit pixels. This would allow your program to continue normally, and SDL would handle the conversion from 24 bits to 16 bits on the fly (with a slight performance loss). The \code{SDL\_UpdateRect} function informs SDL that a portion of the screen has been updated and that it should perform the appropriate conversions to display that area. If a program does not use this function,  it may still work. It is better to be on the safe side, however, and call this function whenever the framebuffer surface has been changed.

\begin{apiref}
\indexc{SDL\_UpdateRect}
\apifunction{SDL\_UpdateRect(surface, left, top, right, bottom)}
\apisynopsis{Updates a specific region of a surface. Normally used to make changes appear on the screen (see text above).}
\apifirstparm{surface}{Surface to update. Usually the screen.}
\apinextparm{left}{Starting $x$ coordinate of the region to update. If all coordinates are zero, \code{SDL\_UpdateRect} will update the entire surface.}
\apinextparm{top}{Starting $y$ coordinate of the region to update.}
\apinextparm{right}{Ending $x$ coordinate of the region to update.}
\apinextparm{bottom}{Ending $y$ coordinate of the region to update.}
\apiendparms
\end{apiref}

\index{SDL!full screen}Finally, if you run the program, you might notice that it runs in a window instead of taking over the entire screen. To change this, replace the zero in the \code{SDL\_SetVideoMode} call with the constant \code{SDL\_FULLSCREEN}. Be careful, though; full-screen applications are harder to debug, and they tend to mess things up badly when they crash. It's a good idea to use normal windowed mode until you're pretty sure your app isn't going to crash.

\subsection{Drawing with Blits}
\label{sect:sdlblitting}
\index{SDL!blitting|(}
\index{blitting|(}
You've seen how to draw pixels directly to a surface, and there's no reason you couldn't create an entire game with this technique alone. However, there is a much better way to draw large amounts of data to the screen. Our next example will load an entire surface from a file and draw it with a single SDL surface-copying function. Without further ado, here is the code.

\begin{codelisting}{blitting-surfaces-sdl.c}{code:blittingsurfacessdl}
\begin{verbatim}
/* Example of simple blitting with SDL. */

#include <SDL/SDL.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
    SDL_Surface *screen;
    SDL_Surface *image;
    SDL_Rect src, dest;

    /* Initialize SDL's video system and check for errors. */
    if (SDL_Init(SDL_INIT_VIDEO) != 0) {
        printf("Unable to initialize SDL: %s\n", SDL_GetError());
        return 1;
    }

    /* Make sure SDL_Quit gets called when the program exits! */
    atexit(SDL_Quit);

    /* Attempt to set a 256x256 hicolor (16-bit) video mode.
       Since 256x256 is rarely a valid video mode, SDL will
       most likely emulate this resolution with a different
       video mode. */
    screen = SDL_SetVideoMode(256, 256, 16, 0);
    if (screen == NULL) {
        printf("Unable to set video mode: %s\n", SDL_GetError());
        return 1;
    }

    /* Load the bitmap file. SDL_LoadBMP returns a pointer to a
       new surface containing the loaded image. */
    image = SDL_LoadBMP("test-image.bmp");
    if (image == NULL) {
        printf("Unable to load bitmap.\n");
        return 1;
    }


    /* The SDL blitting function needs to know how much data
       to copy. We provide this with SDL_Rect structures, which
       define the source and destination rectangles. The areas
       should be the same; SDL does not currently handle image
       stretching. */
    src.x = 0;
    src.y = 0;
    src.w = image->w; /* copy the entire image */
    src.h = image->h;

    dest.x = 0;
    dest.y = 0;
    dest.w = image->w;
    dest.h = image->h;

    /* Draw the bitmap to the screen. We are using a hicolor video
       mode, so we don't have to worry about colormap silliness.
       It is not necessary to lock surfaces before blitting; SDL
       will handle that. */
    SDL_BlitSurface(image, &src, screen, &dest);

    /* Ask SDL to update the entire screen. */
    SDL_UpdateRect(screen, 0, 0, 0, 0);

    /* Pause for a few seconds as the viewer gasps in awe. */
    SDL_Delay(3000);

    /* Free the memory that was allocated to the bitmap. */
    SDL_FreeSurface(image);

    return 0;
}
\end{verbatim}
\end{codelisting}

\index{SDL!loading BMP images}As you can see, the bitmap file is loaded into memory with the \codei{SDL\_LoadBMP} function. This function returns a pointer to an \code{SDL\_Surface} structure containing the image, or a \code{NULL} pointer if the image cannot be loaded. Once this file has been successfully loaded, the bitmap is represented as an ordinary SDL surface, and a program can draw it onto the screen or any other surface. Bitmaps use dynamically allocated memory, and they should be freed when they are no longer needed. The \code{SDL\_FreeSurface} function frees the memory allocated to a bitmap.

\begin{apiref}
\indexc{SDL\_LoadBMP}
\apifunction{SDL\_LoadBMP(filename)}
\apisynopsis{Loads a \filename{.bmp} image file from disk into an SDL surface.}
\apireturns{Pointer to a newly allocated \code{SDL\_Surface} containing the loaded image.}
\apifirstparm{filename}{Name of the bitmap file to load.}
\apiendparms
\end{apiref}

The \codei{SDL\_BlitSurface} function performs a blit of one surface onto another, converting between pixel formats as necessary. This function takes four arguments: a source surface (the image to copy from), an \codei{SDL\_Rect} structure defining the rectangular region of the source surface to copy, a destination surface (the image to copy to), and another \code{SDL\_Rect} structure indicating the coordinates on the destination to which the image should be drawn. These two rectangles must be of the same width and height (SDL does not currently perform stretching), but the $x$ and $y$ starting coordinates of the regions can be different.

\begin{apiref}
\indexc{SDL\_BlitSurface}
\apifunction{SDL\_BlitSurface(src, srcrect, dest, destrect)}
\apisynopsis{Blits all or part of one surface (the source) onto another (the destination).}
\apifirstparm{src}{Source surface. Pointer to a valid \code{SDL\_Surface} structure.}
\apinextparm{srcrect}{Region of the source surface to copy. This is a pointer to an \code{SDL\_Rect} structure. If this is \code{NULL}, SDL will try to copy the entire surface.}
\apinextparm{dest}{Destination surface.}
\apinextparm{destrect}{Region of the destination surface to replace with the source surface. The width and height of the destination surface don't matter; SDL only cares about the $x$ and $y$ coordinates.}
\apiendparms
\end{apiref}

\begin{apiref}
\indexc{SDL\_Rect}
\structname{SDL\_Rect}
\structsynopsis{Specifies regions of pixels. Used for clipping and blitting.}
\structfirstmember{x}{Starting $x$ coordinate.}
\structnextmember{y}{Starting $y$ coordinate.}
\structnextmember{w}{Width of the region, in pixels.}
\structnextmember{h}{Height of the region, in pixels.}
\structendmembers
\end{apiref}

There is really nothing complicated about producing graphics with SDL, once you understand the basics of working with surfaces. If you don't feel comfortable with the \code{SDL\_BlitSurface} function yet, you might want to work with the previous example a bit before moving on. For instance, load several bitmaps and draw them onto each other before blitting them to the screen.

\index{blitting|)}
\index{SDL!blitting|)}

\subsection{Colorkeys and Transparency}
\index{SDL!colorkeys|(}
\index{SDL!transparency|see{SDL, colorkeys}}
\index{colorkeys|(}
Games often need to simulate transparency. For instance, suppose that you have a bitmap of a game character against a solid background, and you want to draw the character in a game level. The character would look silly drawn as is; the background would be drawn too, and the character would be surrounded by a block of solid color. It would be much better to draw only the pixels that are actually part of the character, and not its solid background. You can do this with a \firstterm{colorkey blit}. SDL provides support for this technique, and it even provides support for run-length colorkey acceleration (a nice trick for speeding up drawing). RLE (run-length encoding) provides an enormous performance boost for blitting colorkeyed images, but it is practical only for bitmaps that will not be modified during the course of the program (since modifying an RLE image necessitates unpacking and repacking the image).

A colorkey is a particular pixel value that a program declares to be transparent. (In SDL, this is done with the \codei{SDL\_SetColorKey} function.) Pixels that match an image's colorkey are not copied when the image is blitted. In our example of a game character, you could set the colorkey to the color of the solid background, and it would not be drawn. Colorkeys therefore make it simple to combine rectangular images of nonrectangular objects.

\begin{apiref}
\indexc{SDL\_SetColorKey}
\apifunction{SDL\_SetColorKey(surface, flags, colorkey)}
\apisynopsis{Adjusts the colorkey information for an \code{SDL\_Surface}.}
\apifirstparm{surface}{Surface to modify.}
\apinextparm{flags}{ORed bitmask of colorkey flags. \code{SDL\_SRCCOLORKEY} enables colorkey blitting for this surface. \code{SDL\_RLEACCEL} enables run-length acceleration, which can speed up colorkey operations (but can also slow down \code{SDL\_LockSurface} significantly).}
\apinextparm{colorkey}{If \code{SDL\_SRCCOLORKEY} is set, this specifies the pixel value to use as a colorkey.}
\apiendparms
\end{apiref}

The following example uses a colorkey blit to draw an image of Tux, the Linux penguin, against another image. Tux is stored against a solid blue background, and so we will use blue (RGB 0, 0, 255) as our colorkey. For comparison, we will also draw the same penguin image without a colorkey.

\extfigureheightn{figures/colorkey-example-penguin}{Tuxedo T. Penguin, hero of the Linux world}{2in}

\newpage

\begin{codelisting}{colorkeys-sdl.c}{code:colorkeyssdl}
\begin{verbatim}
/* Example of blitting with colorkeys in SDL. */

#include <SDL/SDL.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
    SDL_Surface *screen;
    SDL_Surface *background;
    SDL_Surface *image;
    SDL_Rect src, dest;
    Uint32 colorkey;

    /* Initialize SDL's video system and check for errors. */
    if (SDL_Init(SDL_INIT_VIDEO) != 0) {
        printf("Unable to initialize SDL: %s\n", SDL_GetError());
        return 1;
    }

    /* Make sure SDL_Quit gets called when the program exits! */
    atexit(SDL_Quit);

    /* Attempt to set a 640x480 hicolor (16-bit) video mode. */
    screen = SDL_SetVideoMode(640, 480, 16, 0);
    if (screen == NULL) {
        printf("Unable to set video mode: %s\n", SDL_GetError());
        return 1;
    }

    /* Load the bitmap files. */
    background = SDL_LoadBMP("background.bmp");
    if (background == NULL) {
        printf("Unable to load bitmap.\n");
        return 1;
    }

    image = SDL_LoadBMP("penguin.bmp");
    if (image == NULL) {
        printf("Unable to load bitmap.\n");
        return 1;
    }

    /* Draw the background. */
    src.x = 0;
    src.y = 0;
    src.w = background->w;
    src.h = background->h;
    dest.x = 0;
    dest.y = 0;
    dest.w = background->w;
    dest.h = background->h;
    SDL_BlitSurface(background, &src, screen, &dest);

    /* Draw the penguin without a colorkey. */
    src.x = 0;
    src.y = 0;
    src.w = image->w;
    src.h = image->h;
    dest.x = 30;
    dest.y = 90;
    dest.w = image->w;
    dest.h = image->h;
    SDL_BlitSurface(image, &src, screen, &dest);

    /* The penguin is stored on a blue background. We
       can use the SDL_MapRGB function to obtain the
       correct pixel value for pure blue. */
    colorkey = SDL_MapRGB(image->format, 0, 0, 255);

    /* We'll now enable this surface's colorkey and draw
       it again. To turn off the colorkey again, we would
       replace the SDL_SRCCOLORKEY flag with zero. */
    SDL_SetColorKey(image, SDL_SRCCOLORKEY, colorkey);
    src.x = 0;
    src.y = 0;
    src.w = image->w;
    src.h = image->h;
    dest.x = screen->w - image->w - 30;
    dest.y = 90;
    dest.w = image->w;
    dest.h = image->h;
    SDL_BlitSurface(image, &src, screen, &dest);

    /* Ask SDL to update the entire screen. */
    SDL_UpdateRect(screen, 0, 0, 0, 0);

    /* Pause for a few seconds as the viewer gasps in awe. */
    SDL_Delay(10000);


    /* Free the memory that was allocated to the bitmaps. */
    SDL_FreeSurface(background);
    SDL_FreeSurface(image);

    return 0;
}
\end{verbatim}
\end{codelisting}

\extfiguren{figures/colorkey-example-output}{Tux, with and without a colorkey}

\index{SDL!colorkeys|)}
\index{colorkeys|)}

\subsection{Loading Other Image Formats}
\index{SDL!loading non-BMP images|(}
SDL provides built-in support for loading \filename{.bmp} files, but this is a fairly limited file format. In particular, it supports only minimal compression and does not provide an alpha channel. (See the next section.) The SDL\_image add-on library adds to SDL support for several different formats, including the popular \filename{.png}, \filename{.jpg}, and \filename{.gif} formats.

SDL\_image is extremely simple to use. Once you have installed the library on your system, your program should include  \filename{SDL/SDL\_image.h} and link with \cmdline{-lSDL\_image}. Assuming this is successful, your programs can use the \code{IMG\_Load} function to load any supported image file format. The next section demonstrates this function.

\begin{shell}
\tt{\$ gcc program.c \verb|-|o program \`{ }sdl-config \verb|--|libs \verb|--|cflags\`{ } \verb|-|lSDL\_image}
\end{shell}

% $

Several other SDL add-on libraries are available, and it is worthwhile to become familiar with them. They can save you a lot of coding footwork in many cases. There are currently libraries for processing TrueType fonts, accessing the network, mixing sound effects, playing music (including MIDI), and managing graphical user interfaces. Most of these libraries are portable, but a few are OS-specific. More information on these libraries is available at \ulink{http://www.libsdl.org}.
\index{SDL!loading non-BMP images|)}

\subsection{Alpha Blending}
\label{sect:sdlalphablending}
\index{SDL!alpha blending|(}
\index{alpha blending|(}
Although graphics and sound are only part of what goes into a successful game, visually impressive games do tend to be more fun than games with lackluster graphics. Game programmers often add special effects to make their graphics stand out. Alpha blending is a special effect that adds varying degrees of translucency to surfaces.

Most images use three color channels (red, green, and blue) to describe each pixel. Alpha blending adds a fourth, the \firstterm{alpha} channel. For this reason, alpha-enabled images are often called \firstterm{RGBA} images. The alpha value of each pixel is an indication of that pixel's opacity. An alpha value of zero indicates that a pixel is completely transparent, and higher alpha values indicate increasing opacity. The alpha channel can be created on the fly according to a program's needs, or it can be stored with an image created in a graphics package.

To draw an RGBA pixel onto another, the alpha function simply performs a weighted average of the two pixels, processing each color channel separately. Suppose that a pixel has RGB values (50,20,30) with an alpha value of 50. This alpha value corresponds to approximately 20 percent opacity (80 percent transparency), since the scale is 0 to 255. If this pixel is drawn on top of a pixel with RGB values (60,80,100), the resulting pixel will take 20 percent of its color from the first pixel and 80 percent of its color from the second, and so its final RGB values will be (58,68,86). This weighted average can be computed with simple arithmetic. Unfortunately, multiplication and division are comparatively slow operations for most processors, so alpha blending generally involves a significant performance hit unless it is supported by a video accelerator.

SDL provides full support for alpha blending. If an image already contains alpha data (from an image-processing program), the \codei{SDL\_SetAlpha} function can be used to enable alpha blending (as you will see in the next example). If the image does not contain an alpha channel, it can still be blended, but the entire surface will have the same opacity value. This is called \firstterm{per-surface} alpha blending. Per-surface alpha blending is also set with \code{SDL\_SetAlpha}.

\begin{apiref}
\indexc{SDL\_SetAlpha}
\apifunction{SDL\_SetAlpha(surface, flags, alpha)}
\apisynopsis{Enables alpha blending on a particular surface.}
\apifirstparm{surface}{The surface to modify.}
\apinextparm{flags}{ORed list of alpha blending flags. \code{SDL\_SRCALPHA} enables alpha blending, and \code{SDL\_RLEACCEL} enables RLE acceleration (with the same ramifications described under \code{SDL\_SetColorKey}).}
\apinextparm{alpha}{Per-surface alpha value. 255 represents complete opacity, and 0 represents complete transparency.}
\apiendparms
\end{apiref}

\newpage
\begin{note}{The Great Alpha Flip}
SDL used to interpret alpha values as \emph{transparency}, not \emph{opacity} (in other words, alpha values now mean exactly the opposite of what they used to -- they now work like the alpha values in nearly every other graphics system). The old style was fine within SDL circles, but it made porting applications that depended on proper alpha support a serious hassle. This idiosyncrasy has been fixed, and it was announced on the SDL development mailing list as the Great Alpha Flip.

This reversal really shouldn't matter, unless you intend to work with truly ancient SDL code that isn't aware of the change.
\end{note}

The next example demonstrates these two types of alpha blending. Since \filename{.bmp} files do not support an alpha channel,\footnote{Some variants of \filename{.bmp} do support an alpha channel, but most image manipulation programs do not write this format. SDL may or may not eventually support bitmap files with alpha data.} we will use the SDL\_image library to read our images from \filename{.png} (Portable Network Graphic) files instead.  Our example will require three image files: one 640 by 480 background image, one 100 by 100 image with an alpha channel, and one 100 by 100 image with no alpha channel.\footnote{I created these images with the GNU Image Manipulation Program (The GIMP, \ulink{http://www.gimp.org}). This is a worthwhile program to learn, even if you're not an artist.} You can get these images from the book's Web site, or make your own.

\begin{codelisting}{alpha-sdl.c}{code:alphasdl}
\begin{verbatim}
/* Example of alpha blending with SDL. */

#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
    SDL_Surface *screen;
    SDL_Surface *background;
    SDL_Surface *image_with_alpha;
    SDL_Surface *image_without_alpha;
    SDL_Rect src, dest;

    /* Initialize SDL's video system and check for errors. */
    if (SDL_Init(SDL_INIT_VIDEO) != 0) {
        printf("Unable to initialize SDL: %s\n", SDL_GetError());
        return 1;
    }

    /* Make sure SDL_Quit gets called when the program exits! */
    atexit(SDL_Quit);

    /* Attempt to set a 320x200 hicolor (16-bit) video mode. */
    screen = SDL_SetVideoMode(320, 200, 16, 0);
    if (screen == NULL) {
        printf("Unable to set video mode: %s\n", SDL_GetError());
        return 1;
    }

    /* Load the bitmap files. The first file was created with
       an alpha channel, and the second was not. Notice that
       we are now using IMG_Load instead of SDL_LoadBMP. */
    image_with_alpha = IMG_Load("with-alpha.png");
    if (image_with_alpha == NULL) {
        printf("Unable to load bitmap.\n");
        return 1;
    }

    image_without_alpha = IMG_Load("without-alpha.png");
    if (image_without_alpha == NULL) {
        printf("Unable to load bitmap.\n");
        return 1;
    }

    background = IMG_Load("background.png");
    if (background == NULL) {
        printf("Unable to load bitmap.\n");
        return 1;
    }

    /* Draw the background. */
    src.x = 0;
    src.y = 0;
    src.w = background->w;
    src.h = background->h;
    dest.x = 0;
    dest.y = 0;
    dest.w = background->w;
    dest.h = background->h;
    SDL_BlitSurface(background, &src, screen, &dest);

    /* Draw the first image, which has an alpha
       channel. We must specifically enable alpha
       blending. */
    SDL_SetAlpha(image_with_alpha, SDL_SRCALPHA, 0);
    src.w = image_with_alpha->w;
    src.h = image_with_alpha->h;
    dest.w = src.w;
    dest.h = src.h;
    dest.x = 40;
    dest.y = 50;
    SDL_BlitSurface(image_with_alpha, &src, screen, &dest);

    /* Draw the second image, which has no alpha
       channel. Instead, we will set a 50% transparency
       factor for the entire surface. */
    SDL_SetAlpha(image_without_alpha, SDL_SRCALPHA, 128);
    src.w = image_without_alpha->w;
    src.h = image_without_alpha->h;
    dest.w = src.w;
    dest.h = src.h;
    dest.x = 180;
    dest.y = 50;
    SDL_BlitSurface(image_without_alpha, &src, screen, &dest);

    /* Ask SDL to update the entire screen. */
    SDL_UpdateRect(screen, 0, 0, 0, 0);

    /* Pause for a few seconds as the viewer gasps in awe. */
    SDL_Delay(3000);


    /* Free the memory that was allocated to the bitmaps. */
    SDL_FreeSurface(background);
    SDL_FreeSurface(image_with_alpha);
    SDL_FreeSurface(image_without_alpha);

    return 0;
}
\end{verbatim}
\end{codelisting}

Look closely at the output of this program. Notice that the background shows through only the outer edges of the first image, but that it shows through the entire second image equally. This is due to the fact that the first image uses a separate alpha value for each pixel, and the second image uses the same alpha value for all of its pixels.

\extfiguren{figures/alpha-example-output}{Output of Listing \ref{code:alphasdl}}

\index{SDL!alpha blending|)}
\index{alpha blending|)}

\subsection{Achieving Smooth Animation with SDL}
\index{SDL!animation|(}
\index{animation|(}
You can now draw simple bitmapped graphics on SDL surfaces (and you could easily learn to do so with other multimedia libraries as well). However, games are not made of static displays. Most games make heavy use of \firstterm{animation}---that is, the simulation of fluid motion---to provide the player with an enjoyable and visually impressive experience.

The basic idea behind computer animation is to rapidly draw a sequence of incrementally changing bitmapped images on the screen over a tightly controlled time interval. Executed properly, this fools the human eye into perceiving smooth movement rather than discrete steps. Each screen update in an animation sequence is called a \firstterm{frame}, and the number of frames drawn in a set period of time is called the \firstterm{framerate}. The quality of an animation depends both on the framerate and on the distance each animated object moves between frames.

Fooling the eye is not easy. If a bitmap moves too quickly, or if completed frames are not displayed frequently enough, the illusion will break down, and the viewer will begin to see each frame as a separate image. This ``jittery'' animation can become very distracting and must be avoided at all costs.

\subsubsection{A First Attempt}
The code listing that follows uses SDL to animate 100 penguins on the screen. These penguins are a bit smaller than the ones in the last example, but they are drawn in the same way. Run this example on your computer to provide a basis for comparison with subsequent examples.

\begin{codelisting}{sdl-anim1.c}{code:sdlanim1}
\begin{verbatim}
/* Animation with SDL -- first attempt. */

#include <SDL/SDL.h>
#include <stdio.h>
#include <stdlib.h>

#define NUM_PENGUINS   100
#define MAX_SPEED      6

/* This structure stores the information for one
   on-screen penguin. */
typedef struct penguin_s {
    int x, y;                  /* position on the screen */
    int dx, dy;                /* movement vector */
} penguin_t, *penguin_p;

/* Array of penguins. */
static penguin_t penguins[NUM_PENGUINS];

/* These are now global variables, for convenience. */
static SDL_Surface *screen;
static SDL_Surface *penguin;

/* This routine loops through the array of penguins and
   sets each to a random starting position and direction. */
static void init_penguins()
{
    int i;

    for (i = 0; i < NUM_PENGUINS; i++) {
        penguins[i].x = rand() % screen->w;
        penguins[i].y = rand() % screen->h;
        penguins[i].dx = (rand() % (MAX_SPEED * 2)) - MAX_SPEED;
        penguins[i].dy = (rand() % (MAX_SPEED * 2)) - MAX_SPEED;
    }
}

/* This routine moves each penguin by its motion vector. */
static void move_penguins()
{
    int i;

    for (i = 0; i < NUM_PENGUINS; i++) {
        /* Move the penguin by its motion vector. */
        penguins[i].x += penguins[i].dx;
        penguins[i].y += penguins[i].dy;

        /* Turn the penguin around if it hits the edge
           of the screen. */
        if (penguins[i].x < 0 || penguins[i].x > screen->w - 1)
            penguins[i].dx = -penguins[i].dx;
        if (penguins[i].y < 0 || penguins[i].y > screen->h - 1)
            penguins[i].dy = -penguins[i].dy;
    }
}

/* This routine draws each penguin to the screen surface. */
static void draw_penguins()
{
    int i;
    SDL_Rect src, dest;

    for (i = 0; i < NUM_PENGUINS; i++) {

        src.x = 0;
        src.y = 0;
        src.w = penguin->w;
        src.h = penguin->h;

        /* The penguin's position specifies its
           center. We subtract half of its width
           and height to get its upper left corner. */
        dest.x = penguins[i].x - penguin->w / 2;
        dest.y = penguins[i].y - penguin->h / 2;
        dest.w = penguin->w;
        dest.h = penguin->h;

        SDL_BlitSurface(penguin, &src, screen, &dest);
    }
}

int main()
{
    SDL_Surface *background;
    SDL_Rect src, dest;
    int frames;

    /* Initialize SDL's video system and check for errors. */
    if (SDL_Init(SDL_INIT_VIDEO) != 0) {
        printf("Unable to initialize SDL: %s\n", SDL_GetError());
        return 1;
    }

    /* Make sure SDL_Quit gets called when the program exits! */
    atexit(SDL_Quit);


    /* Attempt to set a 640x480 hicolor (16-bit) video mode. */
    screen = SDL_SetVideoMode(640, 480, 16, 0);
    if (screen == NULL) {
        printf("Unable to set video mode: %s\n", SDL_GetError());
        return 1;
    }

    /* Load the bitmap files. */
    background = SDL_LoadBMP("background.bmp");
    if (background == NULL) {
        printf("Unable to load bitmap.\n");
        return 1;
    }

    penguin = SDL_LoadBMP("smallpenguin.bmp");
    if (penguin == NULL) {
        printf("Unable to load bitmap.\n");
        return 1;
    }

    /* Set the penguin's colorkey. */
    SDL_SetColorKey(penguin,
                    SDL_SRCCOLORKEY,
                    (Uint16) SDL_MapRGB(penguin->format,
                    0, 0, 255));

    /* Initialize the penguin position data. */
    init_penguins();

    /* Animate 300 frames (approximately 10 seconds). */
    for (frames = 0; frames < 300; frames++) {

        /* Draw the background image. */
        src.x = 0;
        src.y = 0;
        src.w = background->w;
        src.h = background->h;
        dest = src;

        SDL_BlitSurface(background, &src, screen, &dest);


        /* Put the penguins on the screen. */
        draw_penguins();

        /* Ask SDL to update the entire screen. */
        SDL_UpdateRect(screen, 0, 0, 0, 0);

        /* Move the penguins for the next frame. */
        move_penguins();
    }

    /* Free the memory that was allocated to the bitmap. */
    SDL_FreeSurface(background);
    SDL_FreeSurface(penguin);

    return 0;
}
\end{verbatim}
\end{codelisting}

Although this animation may run smoothly on your particular system, it is not optimal for two reasons. First, SDL might or might not be using the video card's actual framebuffer for drawing. If it is using the framebuffer, the penguin graphics will be drawn directly to the screen, and the monitor's refresh might occur while the frame is being composed. This can lead to half-drawn or even missing images on some frames. These problems are known as \index{shearing}\firstterm{shearing} and \index{flicker}\firstterm{flicker}, respectively, and they are even more distracting than jittery animation. Second, the penguin bitmap's pixels are stored in a different format than the screen's pixels, forcing SDL to convert between pixel formats as it draws the images. This is very time-consuming and therefore lowers the framerate of the animation.

\label{sdldoublebuf}
The first problem can be solved with a technique known as \index{SDL!double buffering}\index{double buffering}\firstterm{double buffering}. By specifying the \code{SDL\_DOUBLEBUF} and \code{SDL\_HWSURFACE} flags to \code{SDL\_SetVideoMode}, you can instruct SDL to \emph{always} use a fake (off-screen) framebuffer, even if a direct one is available. This off-screen framebuffer is called a \firstterm{double buffer} or \firstterm{back buffer}. The back buffer can be quickly displayed to the screen with the \codei{SDL\_Flip} function. (Note that the \code{SDL\_UpdateRect} function is not used with double buffering.) Using a second framebuffer for composing the complete frame ensures that everything can be drawn to the screen with one carefully timed blit, rather than the 100 blits our penguin example performs. Double buffering thus significantly mitigates the problems of shearing and flicker.

\newpage
\begin{apiref}
\indexc{SDL\_Flip}
\apifunction{SDL\_Flip(surf)}
\apisynopsis{Swaps the front buffer and the back buffer on a double buffered SDL display. If the display is not double buffered, \code{SDL\_Flip} just updates the entire screen.}
\apifirstparm{surf}{Pointer to the main video surface (returned by \code{SDL\_SetVideoMode}).}
\apiendparms
\end{apiref}

\begin{warning}
The \code{SDL\_DOUBLEBUF} and \code{SDL\_HWSURFACE} flags can actually damage performance or introduce new bugs in some cases. It wouldn't be a bad idea to provide a game option for turning off these flags.
\end{warning}

The second problem is equally simple to avoid. The \codei{SDL\_DisplayFormat} function converts an image's pixels to the correct format for fast blitting. This function accepts a surface as input and creates a new surface that can be displayed without conversion. The old surface can then be freed with \code{SDL\_FreeSurface}.

\begin{apiref}
\indexc{SDL\_DisplayFormat}
\apifunction{SDL\_DisplayFormat(surface)}
\apisynopsis{Converts an image into an optimal format for fast blitting onto the screen.}
\apireturns{Pointer to a newly allocated \code{SDL\_Surface} on success, \code{NULL} on failure. \emph{Don't forget to free the original surface -- this function creates a new surface and doesn't touch the old one. This is a very common memory leak.}}
\apifirstparm{surface}{Pointer to the surface to convert.}
\apiendparms
\end{apiref}

\begin{warning}
The \codei{SDL\_DisplayFormat} function destroys an image's alpha channel, because alpha blending more or less precludes fast blitting (at least without hardware acceleration). Do not use this function on images intended for alpha blending.
\end{warning}

\extfiguren{figures/anim1-example-output}{One frame of the penguin animation}

\subsubsection{An Improved Version}
Our next example integrates both of these improvements, and the resulting animation is considerably smoother. Since the code is largely unchanged, we will not repeat the entire example, only the \code{main} function.

\begin{codelisting}{sdl-anim2.c}{code:sdlanim2}
\begin{verbatim}
int main()
{
    SDL_Surface *temp;
    SDL_Surface *background;
    SDL_Rect src, dest;
    int frames;


    /* Initialize SDL's video system and check for errors. */
    if (SDL_Init(SDL_INIT_VIDEO) != 0) {
        printf("Unable to initialize SDL: %s\n", SDL_GetError());
        return 1;
    }

    /* Make sure SDL_Quit gets called when the program exits! */
    atexit(SDL_Quit);

    /* Attempt to set a 640x480 hicolor (16-bit) video mode
       with a double buffer. */
    screen = SDL_SetVideoMode(640, 480, 16, SDL_DOUBLEBUF);
    if (screen == NULL) {
        printf("Unable to set video mode: %s\n", SDL_GetError());
        return 1;
    }

    /* Load the background image and convert it to the display's
       pixel format. This conversion will drastically improve the
       performance of SDL_BlitSurface, as it will not have to
       convert the surface on the fly. */
    temp = SDL_LoadBMP("background.bmp");
    background = SDL_DisplayFormat(temp);
    if (background == NULL) {
        printf("Unable to load bitmap.\n");
        return 1;
    }
    SDL_FreeSurface(temp);

    /* Load the penguin image. */
    temp = SDL_LoadBMP("smallpenguin.bmp");
    if (temp == NULL) {
        printf("Unable to load bitmap.\n");
        return 1;
    }

    /* Set the penguin's colorkey. Ask for RLE acceleration,
       a technique that can significantly speed up colorkey
       blits. */
    SDL_SetColorKey(temp,
                    SDL_SRCCOLORKEY | SDL_RLEACCEL,
                    (Uint16) SDL_MapRGB(temp->format, 0, 0, 255));

    /* Convert the penguin to the display's format. We do this after
       we set the colorkey, since colorkey blits can sometimes be
       optimized for a particular display. */
    penguin = SDL_DisplayFormat(temp);
    if (penguin == NULL) {
        printf("Unable to convert bitmap.\n");
        return 1;
    }
    SDL_FreeSurface(temp);

    /* Initialize the penguin position data. */
    init_penguins();

    /* Animate 300 frames (approximately 10 seconds). */
    for (frames = 0; frames < 300; frames++) {

        /* Draw the background image. */
        src.x = 0;
        src.y = 0;
        src.w = background->w;
        src.h = background->h;
        dest = src;

        SDL_BlitSurface(background, &src, screen, &dest);

        /* Put the penguins on the screen. */
        draw_penguins();

        /* Ask SDL to swap the back buffer to the screen. */
        SDL_Flip(screen);

        /* Move the penguins for the next frame. */
        move_penguins();
    }

    /* Free the memory that was allocated to the bitmap. */
    SDL_FreeSurface(background);
    SDL_FreeSurface(penguin);

    return 0;
}
\end{verbatim}
\end{codelisting}

The animation produced by this example is drastically improved, mainly due to the much faster blitting. Since we are now explicitly using an off-screen surface for our drawing, we are relatively safe from shearing and flicker. Performance is now in the hands of the X server (which will vary depending on the underlying hardware).

\index{SDL!animation|)}
\index{animation|)}

\index{SDL!video programming|)}

\section{Input and Event Processing}
\index{SDL!events|(}
\index{SDL!input|see{SDL, events}}
SDL uses the notion of \firstterm{events} to report the user's input and window-management actions. For instance, events are produced whenever the user moves the mouse, presses a key, or resizes the SDL video window. A program may use an \firstterm{event loop} to listen to SDL's events. SDL stores unprocessed events in an internal list known as the \index{SDL!event queue}\firstterm{event queue}. This queue allows SDL to collect as many events as possible each time it performs an event update.

\index{SDL!events!event types}There are four main categories of events: keyboard events, mouse events (movement and button clicks), window events (gaining and losing focus, as well as ``exit'' requests), and system-dependent events (raw messages from the windowing system that SDL otherwise would ignore). SDL provides a structure type for recording each kind of event, and these are wrapped by the \codei{SDL\_Event} union. The \code{type} member indicates the particular type of event stored by a \code{SDL\_Event} structure. Most SDL applications use a \code{switch} statement to identify and process the various types of events.

\begin{apiref}
\indexc{SDL\_Event}
\structname{SDL\_Event}
\structsynopsis{Structure for receiving events from SDL. More specifically, a \code{union} of all possible event types.}
\structfirstmember{type}{\code{enum} indicating the type of event. Each event type corresponds to a specialized event structure in the \code{SDL\_Event} union. See \filename{SDL\_events.h} in the SDL API for a list of event types and their corresponding entries in \code{SDL\_Event}; there are quite a few.}
\structendmembers
\end{apiref}

Because every event represents some sort of interaction with the application's main window or console, the SDL event subsystem is closely tied to the video subsystem. Since the two subsystems cannot logically be separated from one another, they are both initialized with the \code{SDL\_INIT\_VIDEO} parameter to \code{SDL\_Init}. It would not make sense to use the event subsystem separately from the video subsystem.

\subsection{Processing Mouse Events}
\index{SDL!events!mouse|(}
The mouse is a fairly simple input device. A mouse (or trackball) reports changes in its position with respect to a fixed unit of measure. For instance, a movement of 1 inch forward and 2 inches to the left (with respect to the mousepad) might correspond to 400 vertical mouse units and $-800$ horizontal units. These units are called \index{mickeys}\firstterm{mickeys}, and their exact meaning varies from mouse to mouse. It is important to realize that, at the lowest level, the mouse has no concept of the screen area or the pointer; it simply measures relative motion.

The code listing that follows demonstrates simple mouse event processing with the SDL event interface.

\begin{codelisting}{mouse-events-sdl.c}{code:mouseeventssdl}
\begin{verbatim}
/* Example of simple mouse input with SDL. */

#include <SDL/SDL.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
    SDL_Surface *screen;
    SDL_Event event;

    /* Initialize SDL's video system and check for errors. */
    if (SDL_Init(SDL_INIT_VIDEO) != 0) {
        printf("Unable to initialize SDL: %s\n", SDL_GetError());
        return 1;
    }

    /* Make sure SDL_Quit gets called when the program exits! */
    atexit(SDL_Quit);

    /* Attempt to set a 256x256 hicolor (16-bit) video mode. */
    screen = SDL_SetVideoMode(256, 256, 16, 0);
    if (screen == NULL) {
        printf("Unable to set video mode: %s\n", SDL_GetError());
        return 1;
    }

    /* Start the event loop. Keep reading events until there
       is an error, or the user presses a mouse button. */
    while (SDL_WaitEvent(&event) != 0) {

        /* SDL_WaitEvent has filled in our event structure
           with the next event. We check its type field to
           find out what happened. */
        switch (event.type) {

            /* The next two event types deal
               with mouse activity. */
        case SDL_MOUSEMOTION:
            printf("Mouse motion. ");

            /* SDL provides the current position. */
            printf("New position is (%i,%i). ",
                   event.motion.x, event.motion.y);

            /* We can also get relative motion. */
            printf("That is a (%i,%i) change.\n",
                   event.motion.xrel, event.motion.yrel);
            break;

        case SDL_MOUSEBUTTONDOWN:
            printf("Mouse button pressed. ");

            printf("Button %i at (%i,%i)\n",
                   event.button.button,
                   event.button.x, event.button.y);
            break;

            /* The SDL_QUIT event indicates that
               the windows "Close" button has been
               pressed. We can ignore this if we
               need to, but that tends to make
               users rather impatient. */
        case SDL_QUIT:
            printf("Quit event. Bye.\n");
            exit(0);
        }
    }

    return 0;
}
\end{verbatim}
\end{codelisting}

This program begins exactly as one of our early SDL video examples did. In fact, it \emph{is} one of our early video examples, minus the drawing code. We need to open a window in order to receive events, but the window's contents are inconsequential. Once the window is open, the program kicks off the event loops and begins to monitor the mouse.

Suppose that the user quickly moves the mouse from the coordinates (10,10) to (25,30), relative to the position of the window. SDL would report this as an \code{SDL\_MOUSEMOTION} event. The event structure's \code{motion.x} and \code{motion.y} fields would contain 25 and 30, respectively. The \code{xrel} and \code{yrel} fields would contain 15 and 20, since the mouse traveled 15 pixels to the right and 20 down. It is possible that this motion would be broken into two or more mouse events (depending on the speed at which the user moved the mouse, among other things), but this can be dealt with by averaging mouse motion over several animation frames.

SDL's event-processing model is sufficient in most cases, but sometimes a program simply needs to know the current position of the mouse, regardless of how it got there. Programs can bypass the event interface entirely with the \codei{SDL\_GetMouseState} function. Unfortunately, this function does not automatically read the mouse's current state; it simply reports the most recently read coordinates. If you choose to bypass the event system, you must call the \code{SDL\_PumpEvents} function periodically to ensure that your program receives up-to-date input device information.

\newpage
\begin{apiref}
\indexc{SDL\_GetMouseState}
\apifunction{SDL\_GetMouseState(x, y)}
\apisynopsis{Returns the current coordinates of the mouse pointer. This is the same information that would be provided through the event interface, but sometimes it's more convenient to poll input devices rather than collect event.}
\apireturns{State of the mouse buttons as a \code{Uint8} (which you can test by ANDing with the \code{SDL\_BUTTON(\emph{num})} macro). Stores the $x$ and $y$ coordinates of the mouse in the given pointers.}
\apifirstparm{x}{Pointer to the integer that should receive the mouse's $x$ coordinate.}
\apinextparm{y}{Pointer to the integer that should receive the mouse's $y$ coordinate.}
\apiendparms
\end{apiref}

\begin{apiref}
\indexc{SDL\_WaitEvent}
\apifunction{SDL\_WaitEvent(event)}
\apisynopsis{Retrieves the next event from SDL's event queue. If there are no events, waits until one is available or something bad happens. On success, copies the new event into the provided \code{SDL\_Event} structure.}
\apireturns{1 on success, 0 on failure.}
\apifirstparm{event}{Pointer to the \code{SDL\_Event} structure that should receive the event.}
\apiendparms
\end{apiref}

\begin{apiref}
\indexc{SDL\_PollEvent}
\apifunction{SDL\_PollEvent(event)}
\apisynopsis{Retrieves the next event from SDL's event queue. If there are no events, returns immediately. On success, copies the new event into the provided \code{SDL\_Event} structure.}
\apireturns{1 if an event was available, 0 otherwise.}
\apifirstparm{event}{Pointer to the \code{SDL\_Event} structure that should receive the event.}
\apiendparms
\end{apiref}

\begin{apiref}
\indexc{SDL\_PumpEvents}
\apifunction{SDL\_PumpEvents()}
\apisynopsis{Checks all input devices for new data. You only need to call this if you intend to bypass the normal event system; \code{SDL\_WaitEvent} and \code{SDL\_PollEvent} call this automatically. If you don't call this, \code{SDL\_GetKeyState} and \code{SDL\_GetMouseState} are unlikely to return correct information. It's common to put this at the top of a game loop.}
\end{apiref}

\begin{warning}
\index{SDL!events!thread safety}
SDL's event processing is not completely thread-safe. In particular, functions that collect new input (\code{SDL\_PollEvent}, \code{SDL\_WaitEvent}, and \code{SDL\_PumpEvents}) should be called only from the thread that originally set the video mode (with \code{SDL\_SetVideoMode}). However, it is safe to call the \code{SDL\_PeepEvents} function (not discussed here) from another thread.

It's possible to have SDL set up a completely separate event-processing thread, but this is only partially implemented and generally unportable. Your best bet is to handle input processing in your game's main thread.
\end{warning}

\index{SDL!events!mouse|)}

\subsection{Processing Keyboard Events}
\index{SDL!events!keyboard|(}
SDL's keyboard event handling is analogous to its mouse event handling, but the keyboard event structure is a bit more complex.

SDL assigns a \index{SDL!virtual keysyms}\firstterm{virtual keysym} to each key on the keyboard. These codes map at some level to the operating system's keyboard scancodes (which in turn map to the codes produced by the keyboard's hardware), but SDL takes care of the mapping behind the scenes. SDL provides a preprocessor symbol for each virtual keysym; for instance, the Escape key corresponds to the symbol \code{SDLK\_ESCAPE}. You use these codes whenever you need to directly check the state (up or down) of a particular key, and SDL uses them to report key events. Virtual keysyms are represented by the \code{SDLKey} type.

\index{SDL!modifier keys}What about the ``special'' keys on the keyboard, such as Ctrl, Alt, and Shift? These do in fact correspond to virtual keysyms, and they can be treated as ordinary keys (you can find their keysyms in \filename{SDL\_keysym.h}); however, they are also considered \firstterm{modifier} keys. Each key event carries information about which modifiers were in effect when the key was pressed. Modifiers are represented by ORed bit flags; for instance, a combination of the left Ctrl and Alt keys would be flagged as \code{(KMOD\_LCTRL | KMOD\_LALT)}. SDL provides the \codei{SDLMod} \code{enum} for representing these combinations. Note that SDL makes a distinction between the left and right modifier keys.

The following example prints out information about SDL keyboard events. It prints the virtual keysym of each key, gives the key's symbolic name, and indicates whether the left Shift key was down when the key was pressed.

\begin{codelisting}{keyboard-events-sdl}{code:keyboardeventssdl}
\begin{verbatim}
/* Example of simple keyboard input with SDL. */

#include <SDL/SDL.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
    SDL_Surface *screen;
    SDL_Event event;

    /* Initialize SDL's video system and check for errors. */
    if (SDL_Init(SDL_INIT_VIDEO) != 0) {
        printf("Unable to initialize SDL: %s\n", SDL_GetError());
        return 1;
    }

    /* Make sure SDL_Quit gets called when the program exits! */
    atexit(SDL_Quit);

    /* Attempt to set a 256x256 hicolor (16-bit) video mode. */
    screen = SDL_SetVideoMode(256, 256, 16, 0);
    if (screen == NULL) {
        printf("Unable to set video mode: %s\n", SDL_GetError());
        return 1;
    }

    printf("Press 'Q' to quit.\n");

    /* Start the event loop. Keep reading events until there
       is an error, or the user presses a mouse button. */
    while (SDL_WaitEvent(&event) != 0) {
        SDL_keysym keysym;

        /* SDL_WaitEvent has filled in our event structure
           with the next event. We check its type field to
           find out what happened. */
        switch (event.type) {

        case SDL_KEYDOWN:
            printf("Key pressed. ");
            keysym = event.key.keysym;
            printf("SDL keysym is %i. ", keysym.sym);
            printf("(%s) ", SDL_GetKeyName(keysym.sym));

            /* Report the left shift modifier. */
            if (event.key.keysym.mod & KMOD_LSHIFT)
                printf("Left Shift is down.\n");
            else
                printf("Left Shift is up.\n");

            /* Did the user press Q? */
            if (keysym.sym == SDLK_q) {
                printf("'Q' pressed, exiting.\n");
                exit(0);
            }

            break;

        case SDL_KEYUP:
            printf("Key released. ");
            printf("SDL keysym is %i. ", keysym.sym);
            printf("(%s) ", SDL_GetKeyName(keysym.sym));

            if (event.key.keysym.mod & KMOD_LSHIFT)
                printf("Left Shift is down.\n");
            else
                printf("Left Shift is up.\n");

            break;

        case SDL_QUIT:
            printf("Quit event. Bye.\n");
            exit(0);
        }
    }

    return 0;
}
\end{verbatim}
\end{codelisting}

It is important to note that a keystroke generates only one event, regardless of how long a key is held down. Games generally use the keyboard as a set of control buttons, not as character input devices, and so the normal key repeat feature is most often of no use to them. However, you can enable key repeat with the \codei{SDL\_EnableKeyRepeat} function. This might be useful for implementing text fields in dialog boxes, for instance.

\begin{apiref}
\indexc{SDL\_EnableKeyRepeat}
\apifunction{SDL\_EnableKeyRepeat(delay, rate)}
\apisynopsis{Enables key repeating. This is usually disabled for games, but it has its uses and is almost always enabled for normal typing.}
\apifirstparm{delay}{Milliseconds to wait after a key is initially pressed before repeating its event. A \code{delay} of 0 disables key repeating. A typical value is somewhere in the range of 250--500.}
\apinextparm{rate}{Milliseconds between repeats. A typical value is 30.}
\apiendparms
\end{apiref}

\index{SDL!direct keyboard access}As with the mouse, it is possible to read the keyboard's state directly, bypassing the event interface. There is no function for directly obtaining the state of an individual key, but a program can obtain a snapshot of the entire keyboard in the form of an array. The \codei{SDL\_GetKeyState} function returns a pointer to SDL's internal keyboard state array, which is indexed with the \code{SDLK\_} keysym constants. Each entry in the array is a simple \code{Uint8} flag indicating whether that key is currently down. Remember to call \codei{SDL\_PumpEvents} before reading the keyboard's state array, or the array's data will not be valid.

\begin{apiref}
\indexc{SDL\_GetKeyState}
\apifunction{SDL\_GetKeyState(numkeys)}
\apisynopsis{Retrieves a snapshot of the entire keyboard as an array. Each entry in the array corresponds to one of the \code{SDLK\_\emph{name}} constants, where 1 means that the corresponding key is currently down and 0 means that the key is currently up. This array pointer will never change during the course of a program; it's one of SDL's internal data structures. Be sure to call \code{SDL\_PumpEvents} periodically, or the keyboard state data will never change.}
\apireturns{Pointer to SDL's keyboard state array. Stores the size of the array in \code{numkeys}.}
\apifirstparm{numkeys}{Pointer to an integer to receive the size of the key array. Most programs don't care about this and just pass \code{NULL}.}
\apiendparms
\end{apiref}

\index{SDL!events!keyboard|)}
 
\subsection{Processing Joystick Events}
\index{SDL!events!joystick|(}
SDL provides a complete interface for joystick management. A modern game can no longer assume that the player will use a traditional two-button, two-axis joystick; many joysticks are equipped with programmable buttons, hat switches, trackballs, and throttles. In addition, some serious gamers like to use more than one joystick at once. Aside from physical limitations (such as the number of ports on a computer or the availability of low-level support from the kernel), SDL can manage any number of joysticks with any number of additional buttons, hats, and trackballs. If the Linux kernel recognizes a device as a joystick, so will SDL.

Joystick axes (directional controls) produce simple linear values indicating their positions. SDL reports these on a scale from $-32,768$ to $32,767$. For instance, the leftmost position of a joystick would produce a value of $-32,768$ on axis 0, and the rightmost position would produce $32,767$. SDL provides the \code{SDL\_JOYAXISMOTION} event type for joystick motion.

\index{SDL!hat switches}Hat switches (small directional controls on top of a joystick) are sometimes represented as additional axes, but they are more frequently reported with a separate \code{SDL\_JOYHATMOTION} event type. Hat positions are reported with respect to the four compass directions and the four diagonals. These positions are numbered clockwise, starting with 1 as North. The center position is 0.\footnote{More recent versions of SDL allow you to access joystick hat positions with a simple bitmask instead of numbers. This change is in effect as of SDL 1.2.}

\begin{warning}
Before you assume that your joystick code isn't working, try running the test programs included with the Linux kernel's joystick driver. If the kernel doesn't know how to deal with your joystick, SDL won't either, and your code will not work.
\end{warning}

The SDL joystick event interface works as you might expect: it generates an event each time the value of a joystick axis or button changes. It also includes functions for polling the state of a joystick directly. The SDL joystick interface is fairly simple, so we won't spend much more time on it.

\begin{codelisting}{joystick-events-sdl.c}{code:joystickeventssdl}
\begin{verbatim}
/* Example of simple joystick input with SDL. */

#include <SDL/SDL.h>
#include <stdlib.h>
#include <stdio.h>

int main()
{
    SDL_Event event;
    SDL_Joystick *js;
    int num_js, i, quit_flag;

    /* Initialize SDL's joystick and video subsystems. */
    if (SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO) != 0) {
        printf("Error: %s\n", SDL_GetError());
        return 1;
    }

    atexit(SDL_Quit);

    /* Create a 256x256 window so we can collect input events. */
    if (SDL_SetVideoMode(256, 256, 16, 0) == NULL) {
        printf("Error: %s\n", SDL_GetError());
        return 1;
    }

    /* Find out how many joysticks are available. */
    num_js = SDL_NumJoysticks();
    printf("SDL recognizes %i joystick(s) on this system.\n",
           num_js);
    if (num_js == 0) {
        printf("No joysticks were detected.\n");
        return 1;
    }

    /* Print out information about each joystick. */
    for (i = 0; i < num_js; i++) {

        /* Open the joystick. */
        js = SDL_JoystickOpen(i);

        if (js == NULL) {
            printf("Unable to open joystick %i.\n", i);
        } else {
            printf("Joystick %i\n", i);
            printf("\tName:       %s\n", SDL_JoystickName(i));
            printf("\tAxes:       %i\n", SDL_JoystickNumAxes(js));
            printf("\tTrackballs: %i\n", SDL_JoystickNumBalls(js));
            printf("\tButtons:    %i\n", SDL_JoystickNumButtons(js));

            /* Close the joystick. */
            SDL_JoystickClose(js);
        }
    }





    /* We'll use the first joystick for the demonstration. */
    js = SDL_JoystickOpen(0);
    if (js == NULL) {
        printf("Unable to open joystick: %s\n", SDL_GetError());
    }

    /* Loop until the user presses Q. */
    quit_flag = 0;
    while (SDL_WaitEvent(&event) != 0 && quit_flag == 0) {
        switch (event.type) {

        case SDL_KEYDOWN:

            if (event.key.keysym.sym == SDLK_q) {
                printf("Q pressed. Exiting.\n");
                quit_flag = 1;
            }

            break;

            /* This event is generated when an axis on an open
               joystick is moved. Most joysticks have two axes,
               X and Y (which will be reported as axes 0 and 1). */
        case SDL_JOYAXISMOTION:

            printf("Joystick %i, axis %i movement to %i\n",
                   event.jaxis.which, event.jaxis.axis,
                   event.jaxis.value);

            break;

            /* The SDL_JOYBUTTONUP and SDL_JOYBUTTONDOWN events
               are generated when the state of a joystick button
               changes. */
        case SDL_JOYBUTTONUP:
            /* fall through to SDL_JOYBUTTONDOWN */

        case SDL_JOYBUTTONDOWN:

            printf("Joystick %i button %i: %i\n",
                   event.jbutton.which,
                   event.jbutton.button, event.jbutton.state);

            break;

        }
    }

    /* Close the joystick. */
    SDL_JoystickClose(js);

    return 0;
}
\end{verbatim}
\end{codelisting} 

\index{SDL!events!joystick|)}
\index{SDL!events|)}

\section{Multithreading with SDL}
\index{threads|(}
\index{SDL!threads|(}
Multithreading is the ability of a program to execute multiple parts of itself simultaneously in the same address space. This feature can be useful to game developers; for instance, a programmer might elect to use separate threads for video processing and music playback so that they can run simultaneously. When properly used, multithreading can simplify game programming and make the end result smoother and more efficient. Threads can significantly boost performance on multiprocessor systems, since each thread can run on a separate processor (this is up to the operating system, though).

Several different thread programming libraries exist for the mainstream operating systems. Windows and Linux use completely different threading interfaces, and Solaris (Sun Microsystems' flavor of UNIX) supports both its own threading API and the one that Linux uses. SDL solves this cross-platform inconsistency with its own set of portable threading functions.

\longpage
Threads are essentially asynchronous procedure calls that return immediately but continue running in the background. \index{SDL!threads!entry point}An SDL thread entry point is simply a pointer to a \code{void} function that takes a \code{void} pointer as a parameter. Threads have their own stacks, but they share the application's global variables, heap, code, and file descriptors. You can start new threads with the \codei{SDL\_CreateThread} function. \code{SDL\_CreateThread} returns a pointer to a \firstterm{thread handle} (of type \codei{SDL\_Thread}) that can be used to interact with the new thread. SDL provides functions for terminating threads (\codei{SDL\_KillThread}) and for waiting for them to finish executing (\codei{SDL\_WaitThread}). Waiting for a thread to finish is sometimes called \index{SDL!threads!joining}\firstterm{joining} the thread.

\begin{apiref}
\indexc{SDL\_CreateThread}
\apifunction{SDL\_CreateThread(func, data)}
\apisynopsis{Starts \code{func} in a separate SDL thread, with \code{data} as an argument. Makes whatever low-level threading calls are appropriate for the given platform (\code{pthread\_create}, in the case of Linux).}
\apireturns{Pointer to an \code{SDL\_Thread} structure that represents the newly created process.}
\apifirstparm{func}{Entry point for the new thread. This function should take one \code{void *} argument and return an integer.}
\apinextparm{data}{\code{void *} to be passed verbatim to \code{func}. This is for your own use, and it's perfectly safe to pass \code{NULL}.}
\apiendparms
\end{apiref}

\begin{apiref}
\indexc{SDL\_KillThread}
\apifunction{SDL\_KillThread(id)}
\apisynopsis{Terminates an SDL thread immediately. If the thread could possibly be doing anything important, it might be a good idea to ask it to end itself rather than just terminating it.}
\apifirstparm{id}{Pointer to the \code{SDL\_Thread} structure that identifies the thread you wish to kill.}
\apiendparms
\end{apiref}

\begin{apiref}
\indexc{SDL\_WaitThread}
\apifunction{SDL\_WaitThread(id)}
\apisynopsis{Waits for an SDL thread to terminate. This is also known as \firstterm{joining} a thread.}
\apifirstparm{id}{Pointer to the \code{SDL\_Thread} structure that identifies the thread you wish to join.}
\apiendparms
\end{apiref}

\label{mutex}
\index{SDL!threads!synchronization}
Multithreaded programming requires a bit of extra caution. What happens if two threads attempt to modify the same global variable at the same time? You have no way of telling which thread will succeed, which can lead to strange and elusive bugs. If there is any chance that two threads will attempt to modify an important data structure simultaneously, it is a good idea to protect the structure with a \firstterm{mutex} (mutual exclusion flag). A mutex is simply a flag that indicates whether a structure is currently in use. Whenever a thread needs to access a mutex-protected structure, it should set (lock) the mutex first. If another thread needs to access the structure, it must wait until the mutex is unlocked. This can prevent threads from colliding, but only if they respect the mutex. SDL's mutexes are advisory in nature; they do not physically block access.

\begin{apiref}
\indexc{SDL\_CreateMutex}
\apifunction{SDL\_CreateMutex}
\apisynopsis{Creates a mutex.}
\apireturns{Pointer to the newly created mutex. This mutex is initially unlocked.}
\end{apiref}

\begin{apiref}
\indexc{SDL\_DestroyMutex(mutex)}
\apifunction{SDL\_DestroyMutex}
\apisynopsis{Frees a mutex.}
\apifirstparm{mutex}{Pointer to the mutex to destroy.}
\apiendparms
\end{apiref}

\begin{apiref}
\indexc{SDL\_mutexP(mutex)}
\apifunction{SDL\_mutexP(mutex)}
\apisynopsis{Locks a mutex. If the mutex is already locked, waits until it is unlocked before locking it again. If you dislike the traditional P/V naming, you can access this function with the \codei{SDL\_LockMutex} macro.}
\apifirstparm{mutex}{Pointer to the mutex to lock.}
\apiendparms
\end{apiref}

\begin{apiref}
\indexc{SDL\_mutexV(mutex)}
\apifunction{SDL\_mutexV(mutex)}
\apisynopsis{Unlocks a mutex. There should always be a \code{SDL\_mutexV} call for every \code{SDL\_mutexP} call. If you dislike the traditional P/V naming, you can access this function with the \codei{SDL\_UnlockMutex} macro.}
\apifirstparm{mutex}{Pointer to the mutex to unlock.}
\apiendparms
\end{apiref}

The example that follows creates three threads that increment a global variable and print out its value. A mutex is used to synchronize access to the variable, so that multiple threads can modify the variable without conflicts.

\begin{codelisting}{sdl-threading.c}{code:sdlthreading}
\begin{verbatim}
/* Example of SDL's portable threading API. */

#include <stdio.h>
#include <stdlib.h>
#include <SDL/SDL.h>

/* We must include SDL_thread.h separately. */
#include <SDL/SDL_thread.h>

static int counter = 0;
SDL_mutex *counter_mutex;

/* The three threads will run until this flag is set. */
static int exit_flag = 0;

/* This function is a thread entry point. */
int ThreadEntryPoint(void *data)
{
    char *threadname;

    /* Anything can be passed as thread data.
       We will use it as a thread name. */
    threadname = (char *) data;

    /* Loop until main() sets the exit flag. */
    while (exit_flag == 0) {
        printf("This is %s! ", threadname);

        /* Get a lock on the counter variable. */
        SDL_mutexP(counter_mutex);

        /* We can now safely modify the counter. */
        printf("The counter is currently %i\n", counter);
        counter++;

        /* Release the lock on the counter variable. */
        SDL_mutexV(counter_mutex);

        /* Delay for a random amount of time. */
        SDL_Delay(rand() % 3000);
    }

    printf("%s is now exiting.\n", threadname);

    return 0;
}

int main()
{
    SDL_Thread *thread1, *thread2, *thread3;

    /* Create a mutex to protect the counter. */
    counter_mutex = SDL_CreateMutex();

    printf("Press Ctrl-C to exit the program.\n");

    /* Create three threads. Give each thread a name
       as its data. */
    thread1 = SDL_CreateThread(ThreadEntryPoint, "Thread 1");
    thread2 = SDL_CreateThread(ThreadEntryPoint, "Thread 2");
    thread3 = SDL_CreateThread(ThreadEntryPoint, "Thread 3");

    /* Let the threads run until the counter reaches 20. */
    while (counter < 20)
        SDL_Delay(1000);

    /* Signal the threads to exit. */
    exit_flag = 1;
    printf("exit_flag has been set by main().\n");

    /* Give them time to notice the flag and exit. */
    SDL_Delay(3500);

    /* Destroy the counter mutex. */
    SDL_DestroyMutex(counter_mutex);

    return 0;
}
\end{verbatim}
\end{codelisting}

If you have used another thread-programming library (such as Win32's threads or the POSIX pthread library), you'll notice that SDL's threading API is somewhat incomplete. For instance, SDL does not allow a program to change a thread's scheduling priority or other low-level attributes. These features are highly dependent upon the operating system, and supporting them in a consistent manner across platforms would be difficult. If your game needs more complete threading abilities, you might consider using a platform-dependent threading toolkit, but this will make your game more difficult to port to other platforms. SDL's threading API is sufficient for almost anything a game might need, though.

\index{threads|)}
\index{SDL!threads|)}
 
\section{SDL Audio Programming}
\label{sect:sdlaudio}
\index{SDL!audio|(}
An often-overlooked but essential area of game programming is sound. Computer sound processing is as much of a science as computer graphics, but the basics of format conversion, mixing, and playback are fairly straightforward. This section discusses the basics of computer audio and investigates SDL's audio-programming interface.

\subsection{Representing Sound with PCM}
\label{sect:pcmsound}
Computer sound is based on pulse-code modulation, or \index{PCM}\firstterm{PCM}. As you know, pixels in a video surface encode the average color intensities of an optical image at regular intervals, and more pixels allow for a closer representation of the original image. PCM data serves the same purpose, except that it represents the average intensities of sequential intervals in sound waves. Each ``pixel'' of PCM data is called a \index{samples}\firstterm{sample}. The rate at which these samples occur is the \index{sampling rate}\firstterm{sampling rate} or \firstterm{frequency} of the sound data. Sampling rates are expressed in the standard SI frequency unit, hertz (Hz). A higher sampling rate allows for a closer representation of the original sound wave.

Individual PCM samples are usually 8 or 16 bits (1 or 2 bytes) for each channel (one channel for mono, two channels for stereo), and game-quality sound is most often sampled at either 22,050 or 44,100 Hz. Samples can be represented as signed or unsigned numbers. A 16-bit sample can obviously express the intensity of a sound with much greater precision than an 8-bit sample, but it involves twice as much data. At 44,100 Hz with 16-bit samples, one second of sound data will consume nearly 90 kilobytes of storage, or twice that for stereo. Game programmers must decide on a trade-off between sound quality and the amount of disk space a game will consume. Fortunately, this trade-off has become less of a problem in recent years, with the advent of inexpensive high-speed Internet connections and the nearly universal availability of CD-ROM drives.

\begin{table}
\begin{center}
\begin{tabular}{|r||c|c|c|c|}
\hline
& \multicolumn{2}{c|}{Mono} & \multicolumn{2}{c|}{Stereo} \\
\cline{2-5}
& 8 bit & 16 bit & 8 bit & 16 bit \\
\hline
\hline
11025 Hz & 11,025 & 22,050 & 22,050 & 44,100 \\
\hline
22050 Hz & 22,050 & 44,100 & 44,100 & 88,200 \\
\hline
44100 Hz & 44,100 & 88,200 & 88,200 & 176,400 \\
\hline
\end{tabular}
\textit{\caption{Storage consumed by various sound formats (in bytes per second)}}
\label{tab:soundrates}
\end{center}
\end{table}

Just as raw pixel data is often stored on disk in \filename{.bmp} files, raw PCM sound samples are often stored on disk in \filename{.wav} files. SDL can read these files with the \codei{SDL\_LoadWAV} function. There are several other PCM sound formats (such as \filename{.au} and \filename{.snd}), but we will confine our discussion to \filename{.wav} files for now. (There is currently no audio file equivalent to the SDL\_image library---are you interested in writing one for us?)

\begin{apiref}
\indexc{SDL\_LoadWAV}
\apifunction{SDL\_LoadWAV(file, spec, buffer, length)}
\apisynopsis{Loads a RIFF \filename{.wav} audio file into memory.}
\apireturns{Non-\code{NULL} on success, \code{NULL} on failure. Fills the given \code{SDL\_AudioSpec} structure with the relevant information, sets \code{*buffer} to a newly allocated buffer of samples, and sets \code{*length} to the size of the sample data, in bytes.}
\apifirstparm{file}{Name of the file to load. The more general \code{SDL\_LoadWAV\_RW} function provides a way to load \filename{.wav} data from nonfile sources (in fact, \code{SDL\_LoadWAV} is just a wrapper around \code{SDL\_LoadWAV\_RW}).}
\apinextparm{spec}{Pointer to the \code{SDL\_AudioSpec} structure that should receive the loaded sound's sample rate and format.}
\apinextparm{buffer}{Pointer to the \code{Uint8 *} that should receive the newly allocated buffer of samples.}
\apinextparm{length}{Pointer to the \code{Uint32} that should receive the length of the buffer (in bytes).}
\apiendparms
\end{apiref}

\begin{apiref}
\indexc{SDL\_FreeWAV}
\apifunction{SDL\_FreeWAV(buffer)}
\apisynopsis{Frees memory allocated by a previous call to \code{SDL\_LoadWAV}. This is necessary because the data might not have been allocated with \code{malloc}, or might be subject to other considerations. Use this function \emph{only} for freeing sample data allocated by SDL; free your own sound buffers with \code{free}.}
\apifirstparm{buffer}{Sample data to free.}
\apiendparms
\end{apiref}

\begin{apiref}
\indexc{SDL\_AudioSpec}
\structname{SDL\_AudioSpec}
\structsynopsis{Contains information about a particular sound format: rate, sample size, and so on. Used by \code{SDL\_OpenAudio} and \code{SDL\_LoadWAV}, among other functions.}
\structfirstmember{freq}{Frequency of the sound in samples per second. For stereo sound, this means one sample per channel per second (i.e., 44,100 Hz in stereo is actually 88,200 samples per second).}
\structnextmember{format}{Sample format. Possible values are \code{AUDIO\_S16} and \code{AUDIO\_U8}. (There are other formats, but they are uncommon and not fully supported---I found this out the hard way.)}
\structnextmember{silence}{PCM sample value that corresponds to silence. This is usually either 0 (for 16-bit signed formats) or 128 (for 8-bit unsigned formats). \emph{Calculated by SDL. Read-only.}}
\structnextmember{channels}{Number of interleaved channels. This will normally be either one (for mono) or two (for stereo).}
\structnextmember{samples}{Number of samples in an audio transfer buffer. A typical value is 4,096.}
\structnextmember{size}{Size of the audio transfer buffer in bytes. \emph{Calculated by SDL. Read-only.}}
\structnextmember{callback}{Pointer to the function SDL should call to retrieve more sample data for playback.}
\structendmembers
\end{apiref}

\index{PCM!mixing}\index{SDL!audio!mixing}PCM data is convenient to work with, despite the necessary size considerations. The key is to realize that PCM is simply a set of measurements that approximate a wave of energy. A strong sound wave will result in large PCM sample values, and a weak sound wave will result in small values. To increase or decrease the volume of a PCM sound wave, simple multiply each sample by a constant. To create a volume-fading effect, multiply each sample by a progressively larger or smaller value. To fade between two samples, simply perform an average with changing weights. Waves are additive; a program can combine (\firstterm{mix}) sounds simply by adding (or averaging) the samples together. Remember that binary numbers have limits; multiplying a sample by a large constant or adding too many samples together is likely to cause an overflow, which will result in distorted sound.
 
\subsection{Feeding a Sound Card}
\index{sound hardware}
A sound card is conceptually simple: it accepts a continuous stream of PCM samples and recreates the original sound wave through a set of speakers or headphones. Your basic task, then, is to keep the sound card supplied with PCM samples. This is a bit of a trick. If you want 44.1 kilohertz (kHz) sound (the quality of sound stored on audio CDs), you must supply the sound card with 44,100 samples per second, per channel. With 16-bit samples and two channels (stereo), this comes out to 176,400 bytes of sound data (see Table \ref{tab:soundrates})! In addition, timing is critical. Any lapse of data will result in a noticeable sound glitch.

It would be both difficult and woefully inefficient to make a game stop 44,100 times each second to feed more data to the sound card. Fortunately, the computer gives us a bit of help. Most modern computer architectures include a feature called \firstterm{direct memory access}, or \index{DMA}\firstterm{DMA}. DMA provides support for high-speed background memory transfers. These transfers are used for a variety of purposes, but their most common use is to shovel large amounts of data to sound cards, hard drives, and video accelerators. You can periodically give the computer's DMA controller buffers of several thousand PCM samples to transfer to the sound card, and the DMA controller can alert the program when the transfer is complete so that it can send the next block of samples.

The operating system's drivers take care of DMA for you; you simply have to make sure that you can produce audio data quickly enough. This is sometimes done with a \index{SDL!audio!callback}\firstterm{callback} function. Whenever the computer's sound hardware asks SDL for more sound data, SDL in turn calls your program's audio callback function. The callback function must \emph{quickly} copy more sound data into the given buffer. This usually involves mixing several sounds together.

This scheme has one small problem: since you send data to the sound card in chunks, there will always be a slight delay before any new sound can be played. For instance, suppose that our program needed to play a gunshot sound. It would probably add the sound to an internal list of sounds to mix into the output stream. However, the sound card might not be ready for more data, so the mixed samples would have to wait. This effect is called \index{SDL!audio!latency}\index{latency}\firstterm{latency}, and you should minimize it whenever possible. You can reduce latency by specifying a smaller sound buffer when you initialize the sound card, but you cannot realistically eliminate it (this is usually not a problem in terms of realism; there is latency in real life, because light travels much faster than sound).

\subsection{An Example of SDL Audio Playback}
\index{SDL!audio!example|(}
We have discussed the nuts and bolts of sound programming for long enough; it is time for an example. This example is a bit lengthier than our previous examples, but the code is fairly straightforward.

\begin{codelisting}{audio-sdl.c}{code:audiosdl}
\begin{verbatim}
/* Example of audio mixing with SDL. */

#include <SDL/SDL.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

/* Structure for loaded sounds. */
typedef struct sound_s {
    Uint8 *samples;     /* raw PCM sample data */
    Uint32 length;      /* size of sound data in bytes */
} sound_t, *sound_p;

/* Structure for a currently playing sound. */
typedef struct playing_s {
    int active;         /* 1 if this sound should be played */
    sound_p sound;      /* sound data to play */
    Uint32 position;    /* current position in the sound buffer */
} playing_t, *playing_p;

/* Array for all active sound effects. */
#define MAX_PLAYING_SOUNDS      10
playing_t playing[MAX_PLAYING_SOUNDS];

/* The higher this is, the louder each currently playing sound
   will be. However, high values may cause distortion if too
   many sounds are playing. Experiment with this. */
#define VOLUME_PER_SOUND        SDL_MIX_MAXVOLUME / 2

/* This function is called by SDL whenever the sound card
   needs more samples to play. It might be called from a
   separate thread, so we should be careful what we touch. */
void AudioCallback(void *user_data, Uint8 *audio, int length)
{
    int i;

    /* Clear the audio buffer so we can mix samples into it. */
    memset(audio, 0, length);

    /* Mix in each sound. */
    for (i = 0; i < MAX_PLAYING_SOUNDS; i++) {
        if (playing[i].active) {
            Uint8 *sound_buf;
            Uint32 sound_len;

            /* Locate this sound's current buffer position. */
            sound_buf = playing[i].sound->samples;
            sound_buf += playing[i].position;

            /* Determine the number of samples to mix. */
            if ((playing[i].position + length) >
                playing[i].sound->length) {
                sound_len = playing[i].sound->length -
                            playing[i].position;
            } else {
                sound_len = length;
            }

            /* Mix this sound into the stream. */
            SDL_MixAudio(audio, sound_buf, sound_len,
                         VOLUME_PER_SOUND);

            /* Update the sound buffer's position. */
            playing[i].position += length;

            /* Have we reached the end of the sound? */
            if (playing[i].position >= playing[i].sound->length) {
                playing[i].active = 0;    /* mark it inactive */
            }
        }
    }
}

/* This function loads a sound with SDL_LoadWAV and converts
   it to the specified sample format. Returns 0 on success
   and 1 on failure. */
int LoadAndConvertSound(char *filename, SDL_AudioSpec *spec,
                        sound_p sound)
{
    SDL_AudioCVT cvt;       /* format conversion structure */
    SDL_AudioSpec loaded;   /* format of the loaded data */
    Uint8 *new_buf;

    /* Load the WAV file in its original sample format. */
    if (SDL_LoadWAV(filename,
                    &loaded, &sound->samples,
                    &sound->length) == NULL) {
        printf("Unable to load sound: %s\n", SDL_GetError());
        return 1;
    }

    /* Build a conversion structure for converting the samples.
       This structure contains the data SDL needs to quickly
       convert between sample formats. */
    if (SDL_BuildAudioCVT(&cvt, loaded.format,
                          loaded.channels, loaded.freq,
                          spec->format, spec->channels,
                          spec->freq) < 0) {
        printf("Unable to convert sound: %s\n", SDL_GetError());
        return 1;
    }

    /* Since converting PCM samples can result in more data
       (for instance, converting 8-bit mono to 16-bit stereo),
       we need to allocate a new buffer for the converted data.
       Fortunately SDL_BuildAudioCVT supplied the necessary
       information. */
    cvt.len = sound->length;
    new_buf = (Uint8 *) malloc(cvt.len * cvt.len_mult);
    if (new_buf == NULL) {
        printf("Memory allocation failed.\n");
        SDL_FreeWAV(sound->samples);
        return 1;
    }

    /* Copy the sound samples into the new buffer. */
    memcpy(new_buf, sound->samples, sound->length);

    /* Perform the conversion on the new buffer. */
    cvt.buf = new_buf;
    if (SDL_ConvertAudio(&cvt) < 0) {
        printf("Audio conversion error: %s\n", SDL_GetError());
        free(new_buf);
        SDL_FreeWAV(sound->samples);
        return 1;
    }

    /* Swap the converted data for the original. */
    SDL_FreeWAV(sound->samples);
    sound->samples = new_buf;
    sound->length = sound->length * cvt.len_mult;

    /* Success! */
    printf("'%s' was loaded and converted successfully.\n",
           filename);

    return 0;
}


/* Removes all currently playing sounds. */
void ClearPlayingSounds(void)
{
    int i;

    for (i = 0; i < MAX_PLAYING_SOUNDS; i++) {
        playing[i].active = 0;
    }
}

/* Adds a sound to the list of currently playing sounds.
   AudioCallback will start mixing this sound into the stream
   the next time it is called (probably in a fraction
   of a second). */
int PlaySound(sound_p sound)
{
    int i;

    /* Find an empty slot for this sound. */
    for (i = 0; i < MAX_PLAYING_SOUNDS; i++) {
        if (playing[i].active == 0)
            break;
    }

    /* Report failure if there were no free slots. */
    if (i == MAX_PLAYING_SOUNDS)
        return 1;

    /* The 'playing' structures are accessed by the audio
       callback, so we should obtain a lock before
       we access them. */
    SDL_LockAudio();
    playing[i].active = 1;
    playing[i].sound = sound;
    playing[i].position = 0;
    SDL_UnlockAudio();

    return 0;
}

int main()
{
    SDL_Surface *screen;
    SDL_Event event;
    int quit_flag = 0;   /* we'll set this when we want to exit. */

    /* Audio format specifications. */
    SDL_AudioSpec desired, obtained;

    /* Our loaded sounds and their formats. */
    sound_t cannon, explosion;

    /* Initialize SDL's video and audio subsystems.
       Video is necessary to receive events. */
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) != 0) {
        printf("Unable to initialize SDL: %s\n", SDL_GetError());
        return 1;
    }

    /* Make sure SDL_Quit gets called when the program exits. */
    atexit(SDL_Quit);

    /* We also need to call this before we exit. SDL_Quit does
       not properly close the audio device for us. */
    atexit(SDL_CloseAudio);

    /* Attempt to set a 256x256 hicolor (16-bit) video mode. */
    screen = SDL_SetVideoMode(256, 256, 16, 0);
    if (screen == NULL) {
        printf("Unable to set video mode: %s\n", SDL_GetError());
        return 1;
    }

    /* Open the audio device. The sound driver will try to give
       us the requested format, but it might not succeed.
       The 'obtained' structure will be filled in with the actual
       format data. */
    desired.freq = 44100;        /* desired output sample rate */
    desired.format = AUDIO_S16;  /* request signed 16-bit samples */
    desired.samples = 4096;      /* this is somewhat arbitrary */
    desired.channels = 2;        /* ask for stereo */
    desired.callback = AudioCallback;
    desired.userdata = NULL;        /* we don't need this */
    if (SDL_OpenAudio(&desired, &obtained) < 0) {
        printf("Unable to open audio device: %s\n", SDL_GetError());
        return 1;
    }

    /* Load our sound files and convert them to
       the sound card's format. */
    if (LoadAndConvertSound("cannon.wav", &obtained,
                            &cannon) != 0) {
        printf("Unable to load sound.\n");
        return 1;
    }

    if (LoadAndConvertSound("explosion.wav",
                            &obtained, &explosion) != 0) {
        printf("Unable to load sound.\n");
        return 1;
    }

    /* Clear the list of playing sounds. */
    ClearPlayingSounds();

    /* SDL's audio is initially paused. Start it. */
    SDL_PauseAudio(0);

    printf("Press 'Q' to quit. C and E play sounds.\n");

    /* Start the event loop. Keep reading events until there is
       an event error or the quit flag is set. */
    while (SDL_WaitEvent(&event) != 0 && quit_flag == 0) {
        SDL_keysym keysym;

        switch (event.type) {

        case SDL_KEYDOWN:
            keysym = event.key.keysym;

            /* If the user pressed Q, exit. */
            if (keysym.sym == SDLK_q) {
                printf("'Q' pressed, exiting.\n");
                quit_flag = 1;
            }

            /* 'C' fires a cannon shot. */
            if (keysym.sym == SDLK_c) {
                printf("Firing cannon!\n");
                PlaySound(&cannon);
            }

            /* 'E' plays an explosion. */
            if (keysym.sym == SDLK_e) {
                printf("Kaboom!\n");
                PlaySound(&explosion);
            }

            break;

        case SDL_QUIT:
            printf("Quit event. Bye.\n");
            quit_flag = 1;
        }
    }

    /* Pause and lock the sound system so we can safely delete
       our sound data. */
    SDL_PauseAudio(1);
    SDL_LockAudio();

    /* Free our sounds before we exit, just to be safe. */
    free(cannon.samples);
    free(explosion.samples);

    /* At this point the output is paused and we know for certain
       that the callback is not active, so we can safely unlock
       the audio system. */
    SDL_UnlockAudio();

    return 0;
}
\end{verbatim}
\end{codelisting}

We begin by initializing SDL as usual, adding the \index{SDL!audio!initializing}\code{SDL\_INIT\_AUDIO} bit flag to specify that SDL should prepare the audio subsystem for use. We also initialize the video subsystem for the purpose of reading keyboard events. Next we install two \code{atexit} hooks: one for the usual \code{SDL\_Quit} function, and one to specifically close the audio device on shutdown. The latter hook is important, as failure to close the audio device properly can result in a segmentation fault when the program exits. At this point the sound card is not actually ready for output; we have only set up SDL's basic infrastructure.

The next step is to initialize the sound card for an appropriate sample format. Our program builds an \codei{SDL\_AudioSpec} structure with the desired sound parameters and calls \codei{SDL\_OpenAudio} to prepare the sound card. Since it is possible that the requested sample format will not be available, \code{SDL\_OpenAudio} stores the \emph{actual} sample format in the \code{SDL\_AudioSpec} structure passed as its second parameter. We can use this structure to convert our sound data to the correct format for playback. Our program requests signed 16-bit samples at 44 kHz. 8-bit sound is lacking in quality, and unsigned 16-bit samples are not supported by SDL.

\begin{apiref}
\indexc{SDL\_OpenAudio}
\apifunction{SDL\_OpenAudio(desired, obtained)}
\apisynopsis{Initializes the computer's sound hardware for playback at the specified rate and sample format. If the requested format isn't available, SDL will pick the closest match it can find. This function does not let you select a particular sound device; if you need to do that, check out the \code{SDL\_InitAudio} function (not documented here, since \code{SDL\_Init} normally takes care of that).}
\apireturns{0 on success, $-1$ on failure. On success, fills \code{obtained} with the rate and sample format of the sound device (which may not be exactly what you requested).}
\apifirstparm{desired}{Pointer to an \code{SDL\_AudioSpec} structure containing the desired sound parameters.}
\apinextparm{obtained}{Pointer to an \code{SDL\_AudioSpec} structure that will receive the sound parameters that SDL was able to obtain.}
\apiendparms
\end{apiref}

\begin{apiref}
\indexc{SDL\_CloseAudio}
\apifunction{SDL\_CloseAudio()}
\apisynopsis{Closes the audio device opened by \code{SDL\_OpenAudio}. It's a good idea to call this as soon as you're finished with playback, so that other programs can use the audio hardware.}
\end{apiref}

\begin{apiref}
\indexc{SDL\_PauseAudio}
\apifunction{SDL\_PauseAudio(state)}
\apisynopsis{Pauses or unpauses audio playback. Playback is initially paused, so you'll need to use this function at least once to start playback.}
\apifirstparm{state}{1 to pause playback, 0 to start playback}
\apiendparms
\end{apiref}

Now that the sound card is initialized and ready for data, our program loads two \filename{.wav} sound files and converts them to the correct format for playback. It uses the information provided by \code{SDL\_OpenAudio} to perform this conversion. The only trick to using SDL's conversion routines is to make sure that there is enough memory to store the converted data. For example, suppose that the sound card expects 16-bit stereo sound at 44 kHz, but the \filename{.wav} file contains 11-kHz, 8-bit mono samples. The conversion would result in eight times as much sample data. SDL performs sample conversions in place, so it is up to our program to ensure that it has allocated a sufficiently large buffer. The end result is that we cannot simply convert the buffer returned by the \codei{SDL\_LoadWAV} function; we must allocate our own buffer and copy the loaded samples into it.

\begin{apiref}
\indexc{SDL\_BuildAudioCVT}
\apifunction{SDL\_BuildAudioCVT(cvt, srcfmt, srcchan, srcfreq, destfmt, destchan, destfreq)}
\apisynopsis{Builds a structure that contains the information necessary for converting between sample formats (src to dest). Use \code{SDL\_ConvertAudio} to actually perform the conversion.}
\apireturns{0 on success, $-1$ on failure.}
\apifirstparm{cvt}{Pointer to an \code{SDL\_AudioCVT} structure that will receive the conversion information.}
\apinextparm{srcfmt}{Sample format of the source sample data. This corresponds to the \code{format} member of \code{SDL\_AudioSpec}.}
\apinextparm{srcchan}{Number of channels in the source sample data. 1 for mono, 2 for stereo.}
\apinextparm{srcfreq}{Frequency in hertz of the source sample data.}
\apinextparm{destfmt}{Sample format of the destination sample data.}
\apinextparm{destchan}{Number of channels in the destination sample data.}
\apinextparm{destfreq}{Frequency in hertz of the destination sample data.}
\apiendparms
\end{apiref}

\begin{apiref}
\indexc{SDL\_ConvertAudio}
\apifunction{SDL\_ConvertAudio(cvt)}
\apisynopsis{Converts the buffer of audio data in \code{cvt->buf} (of length \code{cvt->len} bytes) in-place between sample formats, as set up by a previous call to \code{SDL\_BuildAudioCVT}. Make sure that \code{cvt->buf} is big enough to accept the resulting sample data.}
\apifirstparm{cvt}{Audio conversion structure as described above.}
\apiendparms
\end{apiref}

Our program is now ready to mix and play sounds. It unpauses the SDL audio system by calling \codei{SDL\_PauseAudio} with an argument of zero. SDL will now call the audio callback function several times each second to request sound data. An SDL audio callback takes three arguments: a user-defined pointer (from the \code{SDL\_AudioSpec} structure's \code{userdata} field), an empty audio buffer, and an integer representing the length of the buffer. The callback must fill the audio buffer with the requested amount of audio data, which usually involves mixing samples from several different sound effects together on the fly. Our callback function simply loops through the \code{playing} array and mixes in the next block of samples from each currently playing sound effect. We reduce the volume of each sound effect to prevent the end result from overflowing and becoming distorted.

\begin{warning}
SDL audio callbacks are usually called from a separate thread within SDL. The \code{SDL\_LockAudio} and \code{SDL\_UnlockAudio} functions provide a convenient way to protect audio-related structures from concurrency issues. \code{SDL\_LockAudio} temporarily disables the audio callback, and \code{SDL\_UnlockAudio} enables it. This feature is implemented with a simple mutex.
\end{warning}

The rest of the program simply plays sounds according to keyboard input. To play a sound, we add it to the \code{playing} list and mark it active. The audio callback function then starts mixing this sound into the output the next time it executes.

Once the event loop exits, our program pauses and locks the audio system so that the two sounds (which might otherwise still be playing) can be safely deleted. It is a good idea to unlock the audio system before shutting it down. \code{atexit} then shuts down SDL with \codei{SDL\_CloseAudio} and \code{SDL\_Quit}.

\begin{warning}
Be careful with pointers returned by \code{SDL\_LoadWAV}. They might be allocated in shared memory, and so it is unsafe to free them with the normal \code{free} function. Instead, always use \code{SDL\_FreeWAV} to free these pointers. However, it is perfectly safe to use \code{free} to free sound buffers that you have allocated yourself---provided that the buffers are not currently playing.
\end{warning}

\index{SDL!audio!example|)}
\index{SDL!audio|)}

\section{Integrating OpenGL with SDL}
\index{SDL!OpenGL contexts|(}
\label{sect:sdlopengl}
The OpenGL library is the de facto standard for accelerated 3D graphics under Linux. Designed by Silicon Graphics as a programming interface for its high-performance graphics workstations, OpenGL has been adopted as the preferred 3D API on most major platforms. It is used in many games as well as in professional engineering applications. Microsoft's Direct3D is OpenGL's main competition in the gaming industry, but Direct3D is not a cross-platform solution. SDL hides the platform-dependent details of initializing OpenGL, making it simple to implement accelerated 3D graphics on any major platform.

OpenGL is not difficult to use, but it is a bit tricky to initialize. It is based on \firstterm{rendering contexts}, structures that encapsulate information about the current 3D view settings and the rendering acceleration hardware. In general, OpenGL requires one rendering context for each window that will produce 3D graphics. GLX rendering contexts are not difficult to work with, but SDL handles this for us in a platform-independent manner.

\begin{note}{SDL vs. GLUT}
\index{GLUT!compared with SDL}
\index{SDL!compared with GLUT}
GL Utility Toolkit (GLUT) is a simple OpenGL support library that hides the details of rendering contexts and input devices. It was created by Mark Kilgard (of Silicon Graphics and recently of NVIDIA) as a simple OpenGL demonstration environment. GLUT is intended as a platform for learning OpenGL and for creating proof-of-concept applications, but it is not designed to be a general-purpose multimedia library. This limits its usefulness to game programmers. GLUT is great for giving OpenGL a test drive or for trying new ideas without unnecessary overhead, but SDL is a better platform for serious game development.
\end{note}

Unfortunately, OpenGL more or less takes over the SDL video subsystem. If OpenGL is initialized, direct access to the framebuffer, and any attempt to blit onto the framebuffer, is likely to result in a crash. This is not a very serious limitation, since OpenGL is a fully capable graphics library in itself. You can still create and write to off-screen surfaces, and you can even use SDL surfaces as OpenGL textures. The rest of SDL (audio, input, and so on) is unaffected by OpenGL.

The following example initializes SDL with OpenGL support and renders a colored 3D triangle. If you want to compile and run this program, you will need a copy of the Mesa 3D graphics library (\ulink{http://www.mesa3d.org}) or another Linux OpenGL implementation. Compile and link the program with the \cmdline{-I/usr/X11R6/include -L/usr/X11R6/lib} flags to ensure that the correct header files and libraries can be located. Furthermore, you need to compile your copy of SDL with OpenGL video support.

\begin{codelisting}{opengl-sdl.c}{code:openglsdl}
\begin{verbatim}
/* Example of OpenGL rendering through SDL. */

#include <SDL/SDL.h>
#include <GL/gl.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
    int i;

    /* Initialize SDL as usual. */
    if (SDL_Init(SDL_INIT_VIDEO) != 0) {
        printf("Error: %s\n", SDL_GetError());
        return 1;
    }

    atexit(SDL_Quit);

    /* Enable OpenGL double buffering. */
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

    /* Set the color depth (16-bit 565). */
    SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);

    /* Create a 640x480, 16 bit window with support for
       OpenGL rendering. Unfortunately we won't know
       whether this is hardware accelerated. */
    if (SDL_SetVideoMode(640, 480, 16, SDL_OPENGL) == NULL) {
        printf("Error: %s\n", SDL_GetError());
        return 1;
    }

    /* Set a window title. */
    SDL_WM_SetCaption("OpenGL with SDL!", "OpenGL");

    /* We can now use any OpenGL rendering commands. */
    glViewport(80, 0, 480, 480);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 100.0);
    glClearColor(0, 0, 0, 0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glClear(GL_COLOR_BUFFER_BIT);
    glBegin(GL_TRIANGLES);
    glColor3f(1.0, 0, 0);
    glVertex3f(0.0, 1.0, -2.0);
    glColor3f(0, 1.0, 0);
    glVertex3f(1.0, -1.0, -2.0);
    glColor3f(0, 0, 1.0);
    glVertex3f(-1.0, -1.0, -2.0);
    glEnd();
    glFlush();

    /* Display the back buffer to the screen. */
    SDL_GL_SwapBuffers();

    /* Wait a few seconds. */
    SDL_Delay(5000);

    return 0;
}
\end{verbatim}
\end{codelisting}

Our program begins by initializing SDL as usual and registering \code{SDL\_Quit} with \code{atexit}. \code{SDL\_Quit} is especially important for programs that use OpenGL; Linux's OpenGL support is flaky enough as it is, and forgetting to shut it down properly could cause serious problems. Next we use the \codei{SDL\_GL\_SetAttribute} functions to ask for a double buffer and a 565 hicolor pixel weighting. Finally, we create a 640 by 480, 16-bit output window. We don't care about the video surface that \code{SDL\_SetVideoMode} returns, so we simply check that the returned value is not \code{NULL}. SDL is now initialized with OpenGL support, and we can now use any of OpenGL's rendering commands (the semantics of which are beyond this discussion) to draw on the back buffer.\footnote{We will not cover the OpenGL API in this book; it is sufficient material for many books of its own. With this knowledge, though, you could easily use SDL to run the examples in any OpenGL book.} The \codei{SDL\_GL\_SwapBuffers} function serves the same purpose as \code{SDL\_Flip} does for 2D graphics: it displays OpenGL's back buffer to the screen, allowing for smooth and flicker-free animation.

Now that a rendering context is in place, we can use OpenGL exactly as we would with GLUT or a platform-dependent OpenGL toolkit, and we have SDL's powerful input and audio subsystems at our disposal. SDL gives us everything we need to create high-quality, portable 3D games. Most of Loki Software's 3D game ports use SDL for their OpenGL rendering needs.

\begin{apiref}
\indexc{SDL\_GL\_SetAttribute}
\apifunction{SDL\_GL\_SetAttribute(attr, value)}
\apisynopsis{Sets an OpenGL context attribute. Valid attributes are defined in \filename{SDL\_video.h}. See Listing \ref{code:openglsdl} for examples.}
\apifirstparm{attr}{Attribute to set.}
\apinextparm{value}{Integer value to assign to the attribute.}
\apiendparms
\end{apiref}

\begin{apiref}
\indexc{SDL\_GL\_SwapBuffers}
\apifunction{SDL\_GL\_SwapBuffers()}
\apisynopsis{Swaps the front buffer and the back buffer in a double buffered SDL OpenGL context. Analogous to \code{glutSwapBuffers}.}
\end{apiref}

\index{SDL!OpenGL contexts|)}

\section{Penguin Warrior}
\index{Penguin Warrior!overview|)}
You should now be well versed in the mechanics of SDL. You can initialize the display, draw pixels, blit bitmaps, and even set up SDL for OpenGL rendering. However, these skills are of no use unless you know how to actually use them in a real project. Throughout the rest of the book we will develop a small but playable game called Penguin Warrior, complete with parallaxing graphics, a particle system, network capabilities, background music, and environmental audio.

That's a lot of stuff to cram into one example. We won't do it all at once, however. In this chapter we will code the basic engine, with just enough to let a single player fly a ship around and gawk at the parallaxing background. We'll add environmental audio, music, and network play in later chapters. By the end of the book, we will have created a simple but enjoyable multiplayer game. Due to the size of the source code, the entire \gametitle{Penguin Warrior} listing is not given in this book. You'll find this chapter's files in the \filename{pw-ch4/} subdirectory of the listings archive, which is available on the book's Web site.
\index{Penguin Warrior!overview|)}

\extfiguren{figures/pw-early-screenshot}{An early version of Penguin Warrior}

\index{Penguin Warrior!(lack of) design process}
\gametitle{Penguin Warrior} was conceived to illustrate several of the topics in this book, and as such it is not the product of a formal design process (which is a substantial and complex subject worthy of its own book). Its intent is to demonstrate game programming, not design. The game engine is designed to be easy to understand rather than easy to market. (However, if you think you can make a marketable game out of it, go right ahead!)

Without further ado, let's begin.

\subsection{Creating Graphics}
\index{Penguin Warrior!graphics|(}
Any serious game development team should hire at least one artist and probably more. A professional artist can almost always produce higher-quality game artwork than a programmer. However, it is often useful for programmers to create temporary artwork for the purpose of development. By creating a low-quality set of test artwork (models, images, and even audio effects), a programmer can get a better idea of exactly what to ask of the artist. This temporary artwork can prevent misunderstandings and frustration on the part of both the artist and the programmer. It also gives the programmer something to work with while the artist comes up with higher-quality release artwork.

I created the Penguin Warrior spaceship model in the shareware AC3D modeler\footnote{Although many Linux users (including myself) have a strong preference for free software, AC3D is better than most of the free 3D modellers out there, and it's only \$40 (the unregistered version lacks loading/saving capabilities). A possible free (as in beer, not speech) alternative to AC3D is Blender, but its user interface is about as counterintuitive as they come. Take a pick, or even better, write a new modeller and release it as free software! You can find AC3D at \ulink{http://www.ac3d.org}.} and rendered it at various angles in the free \website{POV-Ray 3.1 raytracer.}{http://www.povray.org} I drew the starry background in the GIMP. Although these aren't professional-quality graphics, they serve their intended purpose, and I had fun creating them.

\extfiguren{figures/ac3d-screenshot}{Creating the Penguin Warrior ship model}

After creating the ship model in AC3D, I exported it to POV-Ray, manually tweaked the camera position in the \filename{.pov} file, and added a \code{clock} variable to allow it to be rotated automatically. I wrote a script to automatically render 96 by 96 images of the model in 4-degree rotation increments (thereby saving the tedious work of rotating the model by hand). The entire rendering process took only a few minutes on a fast laptop. Finally, I used the free ImageMagick package to assemble the individual ship images into one long strip, saved as a bitmap file. I developed this particular procedure throughout several of my own projects, but there are other ways to go about the task of creating 3D graphics with POV-Ray. POV-Ray is worth learning. It can be a great tool for creating prototype graphics, even if you are not a graphic artist, and it can produce amazing images in the hands of a master.
\index{Penguin Warrior!graphics|)}

\subsection{Implementing a Parallaxing Scroller in SDL}
\index{Penguin Warrior!parallaxing scroller|(}
\longpage
Since this game takes place in outer space, one would expect to see stars in the background. These stars should move, or \firstterm{scroll}, as the player flies around. Although this scrolling bears only a faint resemblance to what a pilot would actually see in space, it's common in space games, and this game is not intended to be a realistic simulator.

Penguin Warrior draws its starry background by covering the screen with individual \firstterm{tiles} (small bitmaps) before drawing each frame of animation. Background images tend to be rather repetitive as well as large, and programs can often create them on the fly by putting together tiles in a predetermined pattern. Penguin Warrior generates a two-dimensional array of random tile indices and then draws the starry background by assembling the tiles into a complete image. A 20 by 20 array of 64 by 64 tiles yields a virtual 1280 by 1280 image, using only a fraction of the memory it would take to store the entire image directly. This technique lends itself nicely to random patterns, but it has also been used to generate intricate battlefields for games such as \gametitle{StarCraft} and \gametitle{Civilization}. Tiling can produce ugly results if the tiles look bad to begin with (remember the ``garbage in, garbage out'' principle), but otherwise the only real disadvantage to tiling is code complication. No matter which technique you use to paint our game's background, you'll still have to redraw the entire screen for each frame. This shouldn't be a problem as long as you use standard SDL optimization techniques, such as calling \code{SDL\_DisplayFormat} on our surfaces before using them and avoiding alpha when you can.

\index{parallaxing}Where does parallaxing fit in? Next time you're in a moving car, look out the side window. We tend to take for granted that objects in the distance appear to move past us more slowly than nearby objects. This effect is known as \firstterm{parallax}, and you can exploit it to make your 2D graphics more convincing. Instead of drawing one sheet of tiles in the background, you will draw two (one will obviously have to be transparent or translucent). These layers scroll past the player at different speeds, giving the illusion of depth. To do create a parallax effect, you'll need two sets of background tiles, one with a colorkey (transparent) and one without. You'll also need two tile index arrays, one twice as large as the other (assuming that we want the top layer to scroll twice as fast as the bottom layer).

There is really nothing complicated about parallax scrolling. The only trick is to do it quickly enough to avoid destroying the smooth scrolling effect, and to achieve this you need to squeeze every bit of performance SDL can provide.

Enough rambling; let's dig into some code! The code that follows is from \filename{background.c}, in the \gametitle{Penguin Warrior} source directory for this chapter. It would be a good idea to run the game and observe parallaxing in action, since it is hard to demonstrate motion effects with screen shots.

\begin{codelisting}{background.c}{code:pwparallax}
\begin{verbatim}
#include <time.h>
#include "gamedefs.h"
#include "background.h"
#include "resources.h"

/* Two-dimensional arrays for storing the world's tiles
   (by index). */
static int front_tiles[PARALLAX_GRID_WIDTH][PARALLAX_GRID_HEIGHT];
static int back_tiles[PARALLAX_GRID_WIDTH][PARALLAX_GRID_HEIGHT];

/* This is a simple custom pseudorandom number generator.
   It's not a very good one, but it's sufficient for our
   purposes. Never trust the rand() included with the C library.
   Its quality varies between implementations, and it's easy to
   run into patterns within the generated numbers. At least this
   one is somewhat consistent.
   (Note: You can get fairly decent randomness by taking the high
   order bits of rand()'s output, but you would still be at the
   mercy of the implementation.) */
static Sint32 seed = 0;

static void initrandom()
{
    seed = time(NULL);
}

static unsigned int getrandom()
{
    Sint32 p1 = 1103515245;
    Sint32 p2 = 12345;
    seed = (seed * p1 + p2) % 2147483647;
    return (unsigned) seed / 3;
}

/* Sets up the starry background by assigning random tiles.
   This should be called after LoadGameData(). */
void InitBackground()
{
    int x, y;

    initrandom();
    for (x = 0; x < PARALLAX_GRID_WIDTH; x++) {
        for (y = 0; y < PARALLAX_GRID_HEIGHT; y++) {
            front_tiles[x][y] = getrandom() % num_star_tiles;
            back_tiles[x][y] = getrandom() % num_star_tiles;
        }
    }
}

/* Draws the background on the screen, with respect to the
   global "camera" position. The camera marks the 640x480
   section of the world that we can see at any given time.
   This is usually in the vicinity of the player's ship. */

void DrawBackground(SDL_Surface * dest, int camera_x, int camera_y)
{
    int draw_x, draw_y;   /* drawing position on the screen */
    int start_draw_x, start_draw_y;

    int tile_x, tile_y;   /* indices in the back_tiles[][] array */
    int start_tile_x, start_tile_y;

    /* Map the camera position into tile indices. */
    start_tile_x = ((camera_x / PARALLAX_BACK_FACTOR) /
                    TILE_WIDTH) % PARALLAX_GRID_WIDTH;
    start_tile_y = ((camera_y / PARALLAX_BACK_FACTOR) /
                    TILE_HEIGHT) % PARALLAX_GRID_HEIGHT;

    start_draw_x = -((camera_x / PARALLAX_BACK_FACTOR) %
                     TILE_WIDTH);
    start_draw_y = -((camera_y / PARALLAX_BACK_FACTOR) %
                     TILE_HEIGHT);

    /* Use nested loops to scan down the screen, drawing
       rows of tiles. */
    tile_y = start_tile_y;
    draw_y = start_draw_y;
    while (draw_y < SCREEN_HEIGHT) {
        tile_x = start_tile_x;
        draw_x = start_draw_x;
        while (draw_x < SCREEN_WIDTH) {
            SDL_Rect srcrect, destrect;

            srcrect.x = TILE_WIDTH * back_tiles[tile_x][tile_y];
            srcrect.y = 0;
            srcrect.w = TILE_WIDTH;
            srcrect.h = TILE_HEIGHT;
            destrect.x = draw_x;
            destrect.y = draw_y;
            destrect.w = TILE_WIDTH;
            destrect.h = TILE_HEIGHT;

            SDL_BlitSurface(back_star_tiles, &srcrect,
                            dest, &destrect);

            tile_x++;
            tile_x %= PARALLAX_GRID_WIDTH;
            draw_x += TILE_WIDTH;
        }
        tile_y++;
        tile_y %= PARALLAX_GRID_HEIGHT;
        draw_y += TILE_HEIGHT;
    }
}

void DrawParallax(SDL_Surface * dest, int camera_x, int camera_y)
{
    int draw_x, draw_y;  /* drawing position on the screen */
    int start_draw_x, start_draw_y;

    int tile_x, tile_y;  /* indices in the back_tiles[][] array */
    int start_tile_x, start_tile_y;

    /* Map the camera position into tile indices. */
    start_tile_x = ((camera_x / PARALLAX_FRONT_FACTOR) /
                    TILE_WIDTH) % PARALLAX_GRID_WIDTH;
    start_tile_y = ((camera_y / PARALLAX_FRONT_FACTOR) /
                    TILE_HEIGHT) % PARALLAX_GRID_HEIGHT;

    start_draw_x = -((camera_x / PARALLAX_FRONT_FACTOR) %
                     TILE_WIDTH);
    start_draw_y = -((camera_y / PARALLAX_FRONT_FACTOR) %
                     TILE_HEIGHT);

    /* Use nested loops to scan down the screen, drawing
       rows of tiles. */
    tile_y = start_tile_y;
    draw_y = start_draw_y;
    while (draw_y < SCREEN_HEIGHT) {
        tile_x = start_tile_x;
        draw_x = start_draw_x;
        while (draw_x < SCREEN_WIDTH) {
            SDL_Rect srcrect, destrect;

            srcrect.x = TILE_WIDTH * front_tiles[tile_x][tile_y];
            srcrect.y = 0;
            srcrect.w = TILE_WIDTH;
            srcrect.h = TILE_HEIGHT;
            destrect.x = draw_x;
            destrect.y = draw_y;
            destrect.w = TILE_WIDTH;
            destrect.h = TILE_HEIGHT;

            SDL_BlitSurface(front_star_tiles, &srcrect,
                            dest, &destrect);

            tile_x++;
            tile_x %= PARALLAX_GRID_WIDTH;
            draw_x += TILE_WIDTH;
        }
        tile_y++;
        tile_y %= PARALLAX_GRID_HEIGHT;
        draw_y += TILE_HEIGHT;
    }
}
\end{verbatim}
\end{codelisting}

The \code{InitBackground} function initializes the background drawing system by randomly generating maps of tiles for the top and bottom background layers. It stores this data in the \code{front\_tiles} and \code{back\_tiles} arrays (which can hold 20 by 20 and 40 by 40 tiles, respectively). This code does not seed the random number generator, so the generated maps will be the same each time.

\code{DrawBackground} fills the screen with the appropriate background tiles, relative to the coordinates in the \code{camera\_x} and \code{camera\_y} variables. These variables are updated elsewhere; they usually track the position of the ship within the world. \code{DrawParallax} is similar to \code{DrawBackground}, but it draws the (transparent) parallax layer. It scales the camera coordinates to make the parallax layer move more quickly than the solid layer. These two functions get their starfield tiles from the \code{front\_star\_tiles} and \code{back\_star\_tiles} arrays, which are strips of multiple 64 by 64 tiles stored in the same surface and loaded from the same bitmap file. The tile-drawing loops use a simple calculation to determine the location of the desired tile within the strip, and they rely on \code{SDL\_BlitSurface} to copy the correct rectangle of the strip onto the screen. This is a common and powerful technique---instead of loading graphics as individual surfaces, it is often more convenient to use an image editor to assemble them into a strip and to copy from sections of the strip as needed.

If you don't quite understand how this code works, try charting out the drawing process on graph paper. The basic idea is very simple, but it's easy to make mistakes.
\index{Penguin Warrior!parallaxing scroller|)}

\subsection{A Simple Particle System}
\label{sect:pwparticle}
\index{particle systems|(}
\index{Penguin Warrior!particle system|)}
A \firstterm{particle system} is a set of tiny objects, usually drawn with single pixels or small alpha-blended images, that move under the control of a simulated system of physics. Particle systems can be used for simulated smoke trails, flying sparks, dust effects, and just about anything else that involves small bits of matter. With a little help from a graphics accelerator, particle systems can be used to create breathtaking effects. They can be implemented in many ways, and the particle system implementation in Penguin Warrior is only one possible approach.

Penguin Warrior uses a particle system to simulate explosions. Whenever an object explodes, Penguin Warrior releases thousands of individual visible specks (\firstterm{particles}) onto the playing field. Each particle is assigned a random direction and velocity, originating from the center of the explosion. Each particle is also given a color according to its velocity (roughly approximating the heat of the particle). This is actually a pretty bad simulation of an explosion, but it looks impressive, and that's all that matters (since the particles have no bearing on the actual gameplay).

We've drawn the particles in \gametitle{Penguin Warrior} as single pixels, but it might be an interesting experiment to use alpha blits of small images instead. (This would be slower, and you'd probably want to reduce the number of particles in the system to avoid losing performance.) Alpha-blended particles can result in high-quality eye candy.

Let's take a look at Penguin Warrior's particle code.

\begin{codelisting}{particle.c}{code:pwparticle}
\begin{verbatim}
#include <math.h>
#include <stdlib.h>
#include "gamedefs.h"
#include "particle.h"

particle_t particles[MAX_PARTICLES];
int active_particles = 0;

static void AddParticle(particle_p particle);
static void DeleteParticle(int index);
static Uint16 CreateHicolorPixel(SDL_PixelFormat * fmt, Uint8 red,
                                 Uint8 green, Uint8 blue);

static void AddParticle(particle_p particle)
{
    /* If there are already too many particles, forget it. */
    if (active_particles >= MAX_PARTICLES)
        return;

    particles[active_particles] = *particle;
    active_particles++;
}

/* Removes a particle from the system (by index). */
static void DeleteParticle(int index)
{
    /* Replace the particle with the one at the end
       of the list, and shorten the list. */
    particles[index] = particles[active_particles - 1];
    active_particles--;
}

/* Draws all active particles on the screen. */
void DrawParticles(SDL_Surface * dest, int camera_x, int camera_y)
{
    int i;
    Uint16 *pixels;

    /* Lock the target surface for direct access. */
    if (SDL_LockSurface(dest) != 0)
        return;
    pixels = (Uint16 *) dest->pixels;

    for (i = 0; i < active_particles; i++) {
        int x, y;
        Uint16 color;

        /* Convert world coords to screen coords. */
        x = particles[i].x - camera_x;
        y = particles[i].y - camera_y;
        if ((x < 0) || (x >= SCREEN_WIDTH))
            continue;
        if ((y < 0) || (y >= SCREEN_HEIGHT))
            continue;

        /* Find the color of this particle. */
        color = CreateHicolorPixel(dest->format,
                                   particles[i].r,
                                   particles[i].g,
                                   particles[i].b);

        /* Draw the particle. */
        pixels[(dest->pitch / 2) * y + x] = color;
    }

    /* Release the screen. */
    SDL_UnlockSurface(dest);
}

/* Updates the position of each particle. Kills particles with
   zero energy. */
void UpdateParticles(void)
{
    int i;

    for (i = 0; i < active_particles; i++) {
        particles[i].x += particles[i].energy *
            cos(particles[i].angle * PI / 180.0) * time_scale;
        particles[i].y += particles[i].energy *
            -sin(particles[i].angle * PI / 180.0) * time_scale;

        /* Fade the particle's color. */
        particles[i].r--;
        particles[i].g--;
        particles[i].b--;
        if (particles[i].r < 0)
            particles[i].r = 0;
        if (particles[i].g < 0)
            particles[i].g = 0;
        if (particles[i].b < 0)
            particles[i].b = 0;

        /* If the particle has faded to black, delete it. */
        if ((particles[i].r + particles[i].g +
             particles[i].b) == 0) {
            DeleteParticle(i);

            /* DeleteParticle replaces the current particle with
               the one at the end of the list, so we'll need to
               take a step back. */
            i--;
        }
    }
}

/* Creates a particle explosion of the given relative
   size and position. */
void CreateParticleExplosion(int x, int y, int r, int g, int b,
                             int energy, int density)
{
    int i;
    particle_t particle;

    /* Create a number of particles proportional to the size
       of the explosion. */
    for (i = 0; i < density; i++) {

        particle.x = x;
        particle.y = y;
        particle.angle = rand() % 360;
        particle.energy = (double)(rand() % (energy * 1000)) /
                                  1000.0;

        /* Set the particle's color. */
        particle.r = r;
        particle.g = g;
        particle.b = b;

        /* Add the particle to the particle system. */
        AddParticle(&particle);
    }
}

/* This is directly from another code listing. It creates a
   16-bit pixel. */
static Uint16 CreateHicolorPixel(SDL_PixelFormat * fmt,
                                 Uint8 red, Uint8 green,
                                 Uint8 blue)
{
    Uint16 value;

    /* This series of bit shifts uses the information from the
       SDL_Format structure to correctly compose a 16-bit pixel
       value from 8-bit red, green, and blue data. */
    value = (((red >> fmt->Rloss) << fmt->Rshift) +
             ((green >> fmt->Gloss) << fmt->Gshift) +
             ((blue >> fmt->Bloss) << fmt->Bshift));

    return value;
}
\end{verbatim}
\end{codelisting}

Our particle system is limited to 10,000 particles. That should be plenty, since there will rarely be more than two or three explosions on the screen at once. It is an arbitrary limit; I have tested this code with five times that many particles, but after a point it takes a noticeable toll on the game's framerate.

\code{CreateParticleExplosion} is the main interface to the particle system. This function creates the requested number of particles of a given color and maximum velocity, blasting outward from a given origin. We'll create explosions by calling \code{CreateParticleExplosion} several times, with different velocities and colors. This will allow us to simulate a colorful explosion, with hotter particles closer to the center of the blast. Remember that we care little about proper physics---it's been said that game programming is all about taking as many shortcuts as possible without cheating the player of a good experience. If an explosion looks good, it \emph{is} good.

The other two important particle system routines are \code{UpdateParticles} and \code{DrawParticles}. The former recalculates the position and color of each particle and checks to see whether it should be removed from the system. Particles are removed when they have faded to black and are therefore invisible (since the backdrop is also mostly black). The latter draws a pixel for each currently visible particle. Note that we use the \code{CreateHicolorPixel} routine from a previous example and therefore commit to using a 16-bit framebuffer. It would be fairly simple to modify this to work for 8- or 24-bit surfaces as well, but I doubt it would be worth the effort.

Particle systems are amazingly versatile, and you could easily create custom versions of \code{CreateParticleExplosion} to simulate various types of explosions. The game \gametitle{Heavy Gear II} uses dozens of different types of particle simulations for everything from rain to smoke.
\index{particle systems|)}
\index{Penguin Warrior!particle system|)}

\subsection{Game Timing}
\index{timing|(}
\index{Penguin Warrior!timing|(}
\label{sect:pwtiming}
Try running our SDL animation examples on a computer with a slow video system, and then on a computer with a cutting-edge accelerator supported by X. You will notice a large speed difference between the two, and this disparity can be a serious problem for games. While it is important to draw frames as quickly as possible (30 to 60 per second, if possible), it is also important to make sure that this does not give players with slow hardware an unfair advantage (since speed often corresponds to difficulty).

You have two options for dealing with this disparity in performance: you can lock the framerate at a certain value and simply refuse to run on machines that can't keep up, or you can measure the framerate and adjust the speed of the game accordingly. Most games use the latter option, so as not to exclude gamers with slow computers. It turns out that this is not terribly difficult to implement.

Instead of specifying game object movement in pixels per frame, \gametitle{Penguin Warrior} uses pixels per unit of time (Just about any unit of time would work, but we'll use 1/30th of a second as our baseline, so that a performance of 30 frames per second will result in no adjustment to the game's speed.) To calculate how far each game object should move in a frame, we determine how much time has passed since the last update and scale our movement accordingly. We update a global \code{time\_scale} variable with this information at the start of each frame. Each time we need to move an object, we scale the distance by this amount. We also apply this scaling to acceleration and turning.

Take a look at the \gametitle{Penguin Warrior} code to see how this is done. It's not too complicated, and it lets the game run at its highest performance on any computer.
\index{timing|)}
\index{Penguin Warrior!timing|)}

With the parallaxing code, the particle system, a timing mechanism, and a bit of other SDL voodoo, we now have a working game engine, albeit a simple one. It lacks sound, other players, and weaponry, but we'll add these later on. It's time to take a break from SDL and \gametitle{Penguin Warrior} for a tour of the slightly maddening world of Linux audio. 
