| Games and SDL SDL Installation SDL for Embedded SDL API SDL Events | SDL Graphics SDL Threads Thread Example SDL Animation SDL Sound | Raw Video Player Video Formats Video Compression | Game Trees About The Author |
SDL API
The complete SDL API can be found at http://www.libsdl.org/cgi/docwiki.cgi/SDL_20API. We discuss below some of the basic SDL functions, mainly concerning graphics.
|
Tip: SDL dynamically loads the SDL library from the standard system library locations. Use the SDL_SetLibraryPath() function to use an alternate location for the dynamic libraries distributed with your application. |
| Synopsis |
#include "SDL.h"
int SDL_Init(Uint32 flags); |
|
|---|---|---|
| Description |
Initializes SDL. This should be called before all other SDL functions. The flags parameter specifies what
part(s) of SDL to initialize. (Flags should be bitwise-ORed together, e.g. "SDL_INIT_AUDIO | SDL_INIT_VIDEO".)
SDL_INIT_TIMER Initializes the timer subsystem. SDL_INIT_AUDIO Initializes the audio subsystem. SDL_INIT_VIDEO Initializes the video subsystem. SDL_INIT_CDROM Initializes the cdrom subsystem. SDL_INIT_JOYSTICK Initializes the joystick subsystem. SDL_INIT_EVERYTHING Initialize all of the above. SDL_INIT_NOPARACHUTE Prevents SDL from catching fatal signals. SDL_INIT_EVENTTHREAD Run the event manager in a separate thread. |
|
| Returns | -1 on error, 0 on success. When error occured, you can obtain more information about it by calling SDL_GetError(). |
| Synopsis |
#include "SDL.h"
void SDL_Quit(void); |
|
|---|---|---|
| Description |
Shuts down all SDL subsystems and frees the resources allocated to them.
You can set SDL_Quit as your atexit call for simplicity, like:
atexit(SDL_Quit); |
|
| Returns | none |
| Synopsis |
#include "SDL.h"
void SDL_QuitSubSystem(Uint32 flags); |
|
|---|---|---|
| Description | Shuts down a particular component of SDL, leaving others untouched. |
Example:
#include <stdlib.h>
#include "SDL.h"
main(int argc, char *argv[])
{
if ( SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO) < 0 ) {
fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
exit(1);
}
//atexit(SDL_Quit);
SDL_Quit();
...
}
|
Every personal computer has a video card to process graphical data. There are numerous brands of video cards which differ in structures and functions. To hide the low-level programming details of the video hardware, people introduce the concept of framebuffer device which is an abstraction for the graphic hardware. It represents the frame buffer of some video hardware, and allows application software to access the graphic hardware through a well-defined interface, so that the software doesn't need to know anything about the low-level interface stuff. We may regard framebuffer as an area of memory that describes the image on the computer screen, with each screen pixel corresponding to a memory location.
SDL uses structures called surfaces to handle graphical data. A surface can be regarded as a memory block that stores a retangular region of pixels. Like a framebuffer, a surface has widths, heights, and specific pixel formats. The rectangular region of data of a surface is often referred to as bitmaps or pixmaps.
SDL surfaces can be copied onto each other efficiently with one-to-one pixel mapping, which is referred to as block image transfer or blit. Blit operations are important in game programming as they allow a portion or complete image to be transferred from a memory buffer working in the background to the display screen effectively. Since the framebuffer can be also regarded as a surface, one can display the entire image on the screen with a single blitting operation. In practice, games rely mainly on blits to show the drawings rather than writing to individual pixels one by one. In general, a game's artwork is created by artists and saved in files. The game program assembles the images on screen from those predrawn graphics.
Choosing and setting video modes
Before writing to to the framebuffer, you need to tell the video card what features you need. You can choose your desired bit-depth and resolution, and set it using the SDL_SetVideoMode() function, which returns an SDL_Surface where all graphics data, including the screen, are stored. You can choose a video mode based on the following information: Full screen or windowed, Screen size, Window properties ( has border, resize, .. ), Bits per Pixel, Surface type ( software surface, hardware surface )
The following two examples ask for a 640x480 screen software surface with a pixel format that is that same as the current display setting.
|
|
Example:
//setvideo.cpp
//compile by: g++ -o setvideo setvideo.cpp -I/usr/include -L/usr/local/lib -lSDL
#include <SDL/SDL.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
SDL_Surface *screen;
//initialize video system
if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {
fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
exit(1);
}
//ensure SDL_Quit is called when the program exits
atexit(SDL_Quit);
//set video mode of 640 x 480 with 16-bit pixels
screen = SDL_SetVideoMode(640, 480, 16, SDL_SWSURFACE);
if ( screen == NULL ) {
fprintf(stderr, "Unable to set 640x480 video: %s\n", SDL_GetError());
exit(1);
}
SDL_Delay ( 2000 ); //delay 2 seconds before exit
printf("Setting video mode successful!\n");
return 0;
}
|
|
Drawing pixels on the screen Drawing to the screen is done by writing directly to the graphics framebuffer, and calling the screen update function. Nothing you draw on a software surface is visible until it has been copied from memory to the display buffer on the video card. SDL provides two ways to do that: SDL_Flip() and SDL_UpdateRect(). SDL_Flip() copies the entire software surface to the screen. If your screen is set to 640x480 at 4 bytes per pixel, SDL_Flip() will copy 1.2 megabytes per frame and your frame rate will be limited by how fast your computer can copy images to the screen. SDL_UpdateRects() is designed to let you use a "dirty pixels" scheme. It lets you specify a list of rectangular areas that have been changed and only copies those areas to the screen. This technique is ideal for a game with a complex background but only a small number of moving or changing items. Tracking dirty pixels can give you a dramatic improvement in performance. |
|
| Synopsis |
#include "SDL.h"
int SDL_Flip( SDL_Surface *screen ); |
|
|---|---|---|
| Description | Swaps the background and foreground buffers for systems that support double-buffering. For systems not supporting double-buffering, it is the same as SDL_UpdateRect(screen, 0, 0, 0, 0). | |
| Returns | none
|
| Synopsis |
#include "SDL.h"
void SDL_UpdateRect(SDL_Surface *screen, Sint32 x, Sint32 y, Sint32 w, Sint32 h); |
|
|---|---|---|
| Description |
Makes sure the given area is updated on the given screen. The rectangle must be confined
within the screen boundaries (no clipping is done).
If 'x', 'y', 'w' and 'h' are all 0, SDL_UpdateRect will update the entire screen. |
|
| Returns | none |
The following example draws a pixel on a screen with arbitrary format.
Example:
void DrawPixel(SDL_Surface *screen, Uint8 R, Uint8 G, Uint8 B)
{
|
|
Loading and displaying images
SDL provides one single image loading function, SDL_LoadBMP() for you to load a Windows BMP image onto an SDL surface. The function returns a pointer to an SDL_Surface structure containing the image, or a NULL pointer for failure of loading the image. You can then display the loaded images by using SDL_BlitSurface() to blit them into the graphics framebuffer. SDL_BlitSurface() automatically clips the blit rectangle, which should be passed to SDL_UpdateRect() to update the portion of the screen which has changed. Bitmaps use dynamically allocated memory; if no longer needed they should be freed by using the function SDL_FreeSurface(). Conversely, the function SDL_SaveBMP() allows you to save an SDL surface as a BMP file. |
|
| Synopsis |
#include "SDL.h"
SDL_Surface *SDL_LoadBMP(const char *file); |
|
|---|---|---|
| Description |
Loads a surface from a named Windows BMP file.
Note: When loading a 24-bit Windows BMP file, pixel data points are loaded as blue, green, red, and NOT red, green, blue (as one might expect). |
|
| Returns |
the new surface, or NULL if there was an error.
|
| Synopsis |
#include "SDL.h"
int SDL_BlitSurface(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect ); |
|
|---|---|---|
| Description | Performs a fast blit from the source surface to the destination surface. The width and height in srcrect determine the size of the copied rectangle. Only the position is used in the dstrect (the width and height are ignored). Blits with negative dstrect coordinates will be clipped properly. If srcrect is NULL, the entire surface is copied. If dstrect is NULL, then the destination position (upper left corner) is (0, 0). | |
| Returns |
0 for success, -1 for failure.
|
Example:
void ShowBMP(char *file, SDL_Surface *screen, int x, int y)
{
SDL_Surface *image;
SDL_Rect dest;
/* Load the BMP file into a surface */
image = SDL_LoadBMP(file);
if ( image == NULL ) {
fprintf(stderr, "Couldn't load %s: %s\n", file, SDL_GetError());
return;
}
/* Blit onto the screen surface.
The surfaces should not be locked at this point.
*/
dest.x = x;
dest.y = y;
dest.w = image->w;
dest.h = image->h;
SDL_BlitSurface(image, NULL, screen, &dest);
/* Update the changed portion of the screen */
SDL_UpdateRects(screen, 1, &dest);
}
|
The above image functions only handle images in BMP format. If you need to process images in other popular formats like .png, .jpg or .gif, you need to install the SDL_image- library discussed before. After you have installed it, your program needs to include SDL/SDL_image.h and link with -lSDL_image. Documentation of this library can be found at http://jcatki.no-ip.org/SDL_image/SDL_image.html The library supports BMP, PNM (PPM/PGM/PBM), XPM, LBM, PCX, GIF, JPEG, PNG, TGA, and TIFF formats.
You can use the function IMG_Load() to load an image onto an SDL surface. It is best to call this function outside of event loops, and keep the loaded images around until you are really done with them, as the loading process could be time-consuming. When you have finished using the image, you should use SDL_FreeSurface() to free the allocated resources.
| Synopsis |
#include "SDL_image.h"
SDL_Surface *IMG_Load ( const char *ifile ); |
|
|---|---|---|
| Description | Loads ifile for use as an image onto a new SDL_Surface. | |
| Returns | A pointer to the new SDL_Surface where the image is loaded.
|
Example:
/*
loadimage.cpp
compile by: g++ -o loadimage loadimage.cpp -I/usr/include -L/usr/local/lib -lSDL -lSDL_image
execute by: ./loadimage
*/
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <stdlib.h>
bool load_image ( SDL_Surface *screen, char *image_name, int x, int y )
{
SDL_Surface *image;
SDL_Rect source, offset; //offset is the destination
image = IMG_Load( image_name );
if ( image == NULL ) {
printf ( "Unable to load image\n" );
return false;
}
source.x = 0;
source.y = 0;
source.w = image->w; //display the whole image
source.h = image->h;
offset.x = x; //position to display the image
offset.y = y;
offset.w = image->w; //the width and height here actually are NOT used
offset.h = image->h;
//Draws the image data to the screen: (image, source) is the source, (screen, offset) is the destination
SDL_BlitSurface ( image, &source, screen, &offset );
//free the resources allocated to image
SDL_FreeSurface ( image );
return true;
}
int main()
{
SDL_Surface *screen;
//initialize video system
if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {
fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
exit(1);
}
//ensure SDL_Quit is called when the program exits
atexit(SDL_Quit);
//set video mode of 640 x 480 with 16-bit pixels
screen = SDL_SetVideoMode(640, 480, 16, SDL_SWSURFACE);
if ( screen == NULL ) {
fprintf(stderr, "Unable to set 640x480 video: %s\n", SDL_GetError());
exit(1);
}
//put image near center of screen
if ( !load_image ( screen, "test-image.gif", 320, 240 ) ) {
exit ( 1 );
}
//update the entire screen
SDL_UpdateRect ( screen, 0, 0, 0, 0 );
SDL_Delay ( 4000 ); //delay 4 seconds before exit
return 0;
}
|