Friday, December 29, 2006

Game Programming using SDL: Getting Started

Game programmers using OpenGL have often been forced to make a choice between using a library that is platform independent but doesn't use all the available resources, or powerful but platform dependent. Simple Directmedia Layer (SML) offers a third way. This article will give you a taste of its capabilities.

Game programming has come a long way since early Linux and Windows days. The time is gone when games were limited to Windows or to an extended Mac. Today portability is in the forefront, even in the gaming segment. The birth of OpenGL was the first step in this regard. But OpenGL addressed only the rendering aspect of game programming. The major part, that is communicating with varied input devices, was left to the operating system. That is the reason for the existence of various extensions to OpenGL, including GLUT (platform independent), MESA (OpenGL extension for *nix systems) and WOGL (OpenGL extension for Windows).

Each of these has its own pros and cons. If a library is OS independent, then it is limited in utilization of all the available resources. If it is able to harness the power of the underlying system, then such a library is platform dependent. Apart from portability issues, all the existing libraries left the task of developing the gaming infrastructure on the shoulders of the developer. It was during such times of extreme choices that SDL came into picture.

SDL (Simple Directmedia Layer) is a library "by the game programmers for the game programmers." Hence it doesn't try to achieve the "unachievable" by starting from scratch. Instead it is built upon the existing libraries for each OS, i.e. it uses DirectX for Windows and XWindows APIs for *nix systems. Additionally, SDL provides for all the infrastructure needs of a varied range of games.

In this discussion, I will focus on setting up SDL and accessing one of its many infrastructure facilities -- loading a sprite. In the first section I will enumerate the infrastructure services. The second section will focus on the initializing the video to achieve the best resolution. In the third section, I will discuss how to load a bitmap using SDL APIs. The third section will also detail the real world implementation of using an SDL API for sprite loading.

SDL: The Services Provided

The implementation works in such a way that it never gets in the way of a programmer's code, as is evident from the services provided by SDL. In a nutshell one can say that it follows the philosophy of SMILE (Simple Makes It a Lot Easier) which is evident from the following services provided by it:

1. Initialization and Shutdown
2. Input processing
3. Timers
4. Sound effects
5. Graphics manipulation
6. Network integration
7. Threading requirements

Of these services, the first five are the basis of any game. SDL makes dealing with each of them easier. Let's see how.

1. Initialization and Shutdown:

Whenever a game starts, it must perform initialization routines including memory allocation, resource acquisition, loading any required data from the disk, and so forth. To perform these routines, the programmer has to query the underlying OS to know the boundaries set by it. To achieve this end some code must be written, and code must be written again to use the result of the query. SDL abstracts this with a single function: SDL_Init().

2. Input Processing:

In a gaming environment the input can come from the keyboard, joystick, mouse and so on. The processing model provided by SDL is event based. Anyone who has worked in VB, Delphi or Xlib (or any of its variants) will feel at home with SDL's event model. The base of this model is the SDL_WaitEvent() method that takes SDL_Event as a reference.

3. Timers:

Without timers it is nearly impossible to imagine any challenging game. If one goes by standard methods, one would have to rely on the timers provided by the platform. But with SDL, this is a thing of past. The Time and Timer APIs provided by it are lean, mean and clean in a platform and OS independent way. SDL_getTicks() is the core of the SDL Timer API.

4. Sound Effects:

As with other functionalities provided by SDL, the functionalities related to sound are provided with minimum hassles. The sound support as a core sub-system is minimal in nature, adhering to the keep-it-lean philosophy of SDL. But there are other libraries that provide extended capabilities around SDL's APIs.

5. Graphics Manipulation:

With SDL one has the option of working at the raw pixel level or at a higher level using OpenGL. Since OpenGL is available for every platform and it can render both 2D and 3D graphics in hardware accelerated mode, it is better to use OpenGL in conjunction with SDL.

6. Networking Requirements:

Like other functionalities, networking is also important in the current genre of games. Understanding this importance, the developers of SDL provided an APIs that does the ground-level work to set up the network connections and manage them, thus making networked multiplayer games less of an enigma.

7. Threading Requirements:

The pthreads library provided by POSIX is a platform independent way of working with threads. But the API works at a low level, which can be confusing. To make threading simpler, SDL provides all the required functionalities in a high-level manner.

In essence, SDL provides for all gaming requirements in a simple and portable way. Now that the introduction to the functionalities is out of our way, we can actually see how the theory works by looking at how handling the video subsystem works.