Chapter 2 – Getting Started with SDL

Okay then. Let’s to get started by creating a sample program.

#include <SDL/SDL.h>

int main(int argc, char* argv[])
{
    /* A pointer to the video surface */
    SDL_Surface* screen = NULL;

    /* Initialize SDL's video sub-system */
    if (SDL_Init(SDL_INIT_VIDEO) < 0)
        fprintf(stderr, SDL_GetError());

    /* Quit SDL on exit */
    atexit(SDL_Quit);

    /* Create a double buffered window 640 pixels wide and 480 pixels long */
    screen = SDL_SetVideoMode(640, 480, 16, SDL_HWSURFACE|SDL_DOUBLEBUF);

    /* Error check */
    if (!screen) fprintf(stderr, SDL_GetError());

    /* Wait 5 seconds */
    SDL_Delay(5000);

    /* Destroy the video surface */
    SDL_FreeSurface(screen);

    return 0;
}

Now, to give you a brief walkthrough…

    /* A pointer to the video surface */
    SDL_Surface* screen = NULL;

Here we declare an SDL_Surface pointer to hold the SDL_Surface object that represents the screen. Using SDL_Surfaces is a generic way of drawing stuff. Something like HDCs in GDI. The same code can be used to draw on the screen that you use to draw in memory.

Surfaces can be copied onto one another (SDL_BlitSurface), or filled with a color (SDL_FillRect) etc. Here’s the declaration:

typedef struct SDL_Surface {
    Uint32 flags;                           /* Read-only */
    SDL_PixelFormat *format;                /* Read-only */
    int w, h;                               /* Read-only */
    Uint16 pitch;                           /* Read-only */
    void *pixels;                           /* Read-write */
    SDL_Rect clip_rect;                     /* Read-only */
    int refcount;                           /* Read-mostly */

  /* This structure also contains private fields not shown here */
} SDL_Surface;

Onto the next snippet.

    /* Initialize SDL's video sub-system */
    if (SDL_Init(SDL_INIT_VIDEO) < 0)
        fprintf(stderr, SDL_GetError());

This initializes SDL and it’s various sub-systems. I used the SDL_INIT_VIDEO flag to initialize the video sub-system. See here for a list of flags to use with this function. To simply initialize everything just use the SDL_INIT_EVERYTHING flag. The function returns 0 on success and -1 on failure (hence the if ... < 0 statement for error checking). Also note that stderr is already redirected to a text file stderr.txt by SDL.

    /* Quit SDL on exit */
    atexit(SDL_Quit);

This is to ensure that the SDL_Quit()function is called before the program exits. This un-initializes all previously initialized sub-systems and shuts down SDL.

    /* Create a double buffered window 640 pixels wide and 480 pixels long */
    screen = SDL_SetVideoMode(640, 480, 16, SDL_HWSURFACE|SDL_DOUBLEBUF);

This creates a window with a width of 640 and height of 480 pixels. The third parameter is bits-per-pixel, you usually use values like 16, 24 and 32. The last parameter are the display flags. I used SDL_HWSURFACE because I wanted a hardware-surface (i.e a surface stored in video memory instead of system memory). Hardware surfaces tend to be faster than software ones. Secondly, the SDL_DOUBLEBUFflag tells SDL we want a double buffered window mode. Double Buffered means we want SDL to draw first draw on a separate surface in memory (the back-buffer) and then copy the back buffer onto the screen (front-buffer), instead of directly drawing on the screen. This allows for smoother graphics.

    /* Error check */
    if (!screen) fprintf(stderr, SDL_GetError());

The SDL_SetVideoMode() function returns a NULL on failure. So this is just a simple error check.

    /* Wait 5 seconds */
    SDL_Delay(5000);

The SDL_Delay function waits for a specific number of milliseconds. It isn’t very accurate however and shouldn’t be used in doing precise calculations. Over here we just use it to give us 5 seconds (1 s = 1000 ms) to look at our window before it closes.

    /* Destroy the video surface */
    SDL_FreeSurface(screen);

The SDL_FreeSurface() function frees up the memory and resources taken up by a previously created surface. Freeing surfaces you have created is good practice. The surface should also be assigned a NULL value after freeing to ensure that it doesn’t do something unpredictable if accidentally used after it is freed. Since SDL_Surfaces are reference counted, you don’t have to worry about accidentally freeing a surface which is being used somewhere else. If it’s in use, it isn’t freed and deleted. However take care to call SDL_FreeSurface() only once for every surface you create. Since we already added SDL_Quit to atexit() we don’t need to call it here.

To compile SDL applications, you have to include SDL’s include directory to your compiler’s search paths, and link with SDL.dll. On MinGW GCC, I usually use this makefile for compiling SDL Apps:

CC=gcc
COMPILER_DIRS=-I
LINKER_DIRS=-L -L

#Change this when adding more source files
SOURCES=<source files="" />
OBJECTS=$(SOURCES:.cpp=.o)

CFLAGS=-Wall $(COMPILER_DIRS) $(LINKER_DIRS)
LIBS=-l mingw32 -l SDLmain -l SDL
TARGET=-mwindows
EXECUTABLE=bin\game.exe

$(EXECUTABLE): $(OBJECTS)
	$(CC) $(OBJECTS) $(CFLAGS) -o $@ $(LIBS)

%.o : %.cpp
	$(CC) -c $< -o $@ $(CFLAGS)

clean:
	del *.o

, and ¬† should be replaced with SDL’s include, lib and bin directories. For example if SDL is in C:\, should be C:\SDL\include. Replace with your source files.

If the app is successfully built, it should display a blank unresponsive window for about 5 seconds and then shut down. That’s pretty much the infrastructure of an SDL Application.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s