Originally Published: Monday, 25 June 2001 Author: Josh Boudreau
Published to: develop_articles_tutorials/Development Tutorials Page: 3/4 - [Printable]

Programming Linux Games: An Introduction to SDL Development

Welcome to Game Week on Linux.com! All this week we'll be featuring and playing games. The game week feature article by Linux.com writer Josh "bitwize" Boudreau is a succinct introduction to programming with the SDL (Simple DirectMedia Layer) library, essential to understanding Linux game development. So all you game programmers or would be game programmers: read up!

Video  << Page 3 of 4  >>

Video

SDL provides many functions to use video and graphics features. Before jumping into video functions I will explain a common data type we will be using. Most video and graphic functions take a SDL_Surface structure. You could think of this data type as a drawable surface. The SDL_Surface structure holds information about our drawable surface like width, height and the actual data of the pixels used by our surface. SDL_Surface structures are used both to give access to the current screen and also provide storage for graphics.

To start using video functions you must first call SDL_SetVideoMode(). This function will create a window and return a pointer to the video surface. SDL_SetVideoMode()'s argument specify the width, height and bps of our video surface. This function also takes unsigned int flags to specify which type of video surface we want. SDL_SetVideoMode() is defined like this:

SDL_Surface *SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags);

Here are a few flags you can pass to the function, for more you should read the SDL_SetVideoMode man page by typing man SDL_SetVideoMode at your shell prompt.

SDL_SWSURFACE
SDL_HWSURFACE
SDL_DOUBLEBUF
SDL_FULLSCREEN
SDL_OPENGL

SDL_SWSURFACE will create a video surface in system memory while SDL_HWSURFACE will create one in video memory. SDL_DOUBLEBUF will create a double buffered window and SDL_FULLSCREEN will set the specified video resolution instead of creating a window of the same size. SDL_OPENGL is used when you need OpenGL rendering. Here's an example using the SDL_SetVideoMode() function.

SDL_Surface *screen;

screen = SDL_SetVideoMode(800, 600, 16, SDL_SWSURFACE | SDL_FULLSCREEN);
if(screen == NULL)
{
fprintf(stderr, "Unable to set video mode: %s\n", SDL_GetError());
return -1;
}

Sometimes when you access the video memory to change pixel values the video surface will need to be locked. SDL provides a macro to check if the video memory needs to be locked, or not. This macro is SDL_MUSTLOCK(SDL_Surface). Even if you know the video surface does not need locking, it's a good idea to check anyway by enclosing all the drawing functions between if statements checking if locking is needed. Here's a small example.

SDL_Surface *screen;

screen = SDL_SetVideoMode(800, 600, 16, SDL_SWSURFACE | SDL_FULLSCREEN);

if(SDL_MUSTLOCK(screen))
SDL_LockSurface(screen);

/*(You can write and access video memory here)*/

if(SDL_MUSTLOCK(screen))
SDL_UnlockSurface(screen);

Like I mentioned previously, graphics are also loaded into SDL_Surface structures. SDL support BMP graphics files and they can be loaded with the SDL_LoadBMP() function. SDL_LoadBMP() takes a single argument which is the filename that we would like to load. It then returns a pointer to a SDL_Surface structure which holds the image data. Once loaded, images can be written on the screen with the SDL_BlitSurface() function. SDL_BlitSurface is defined like this:

int SDL_BlitSurface(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect);

Here we see another data structure, SDL_Rect. This structure hold four integer values, x, y, w and h. This data structure is used to tell functions about x,y positions, width and height. SDL_BlitSurface takes two SDL_Rect other than the source and destination surfaces and are used to tell which part of the image we want to blit and also where on the screen we would like the image to be positioned. If the SDL_Rect structures in the SDL_BlitSurface function are NULL, the function assumes we want to blit the whole surface at 0,0. Here's an example demonstrating the use the SDL_LoadBMP and SDL_BlitSurface.

SDL_Surface *screen;
SDL_Surface *image;

screen = SDL_SetVideoMode(800, 600, 16, SDL_SWSURFACE);
if(screen == NULL)
{
fprintf(stderr, "Unable to set video mode: %s\n", SDL_GetError());
return 0;
}

image = SDL_LoadBMP("graphic.bmp");
if(image == NULL)
{
fprintf(stderr, "Unable to load graphic file: %s\n", SDL_GerError());
return 0;
}

while(1)
{
if(SDL_MUSTLOCK(screen))
SDL_LockSurface(screen);

SDL_BlitSurface(image, NULL, screen, &rect);

if(SDL_MUSTLOCK(screen))
SDL_UnlockSurface(screen);

SDL_UpdateRect(screen, 0,0,0,0);
}

In this example we set up our video mode and load a graphic file. Once loaded the program goes into the never-ending loop and displays our graphic on the screen. The new function SDL_UpdateRect() is used to update the part of the screen we blitted the image on. I pass all zeros to the function to update the whole screen. If you want to only update part of the screen you can pass x, y, w, h values. If you would have specified SDL_DOUBLEBUF as a video flag, you would use SDL_Flip(screen) which would flip the buffers and display the graphics.





Video  << Page 3 of 4  >>