SDL: The basics
SDL is a fairly low-level API, which means it doesn't do that much of the work for you. It will interface in a satisfactory way with your OS and hardware, but it won't do many of the tasks that more complex libraries can perform.
This guide is intended to show you the bare essentials of writing a program using SDL, if you want more complex information on how the library works or want to use some of the more advanced features, please see the SDL Documentation
Initializing the library
To set up SDL ready for use you will need to use the SDL_Init function, specifying the subsystems that you would like to use. Subsystems are things like video, audio, timing, or cd-rom control. You use it like this:
SDL_Init(flags);
//Example: initialise the audio and video subsystems
SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO);
Where flags can be any bitwise OR'ed (use the pipe | symbol) combination of
- SDL_INIT_TIMER
- SDL_INIT_AUDIO
- SDL_INIT_VIDEO
- SDL_INIT_CDROM
- SDL_INIT_JOYSTICK
- SDL_INIT_NOPARACHUTE
- SDL_INIT_EVENTTHREAD
Or the special flag SDL_INIT_EVERYTHING which initialises all of the subsystems. The last two on the list are for complex and multi-threaded programming, so you probably don't need to concern yourself with them right now. In fact, most of my programs only use the SDL_INIT_VIDEO subsystem.
Initializing and creating the video surface
To set up video in SDL, you need the SDL_SetVideoMode function. This takes parameters specifying the kind of setup you want and returns a pointer to the display surface. This is what you will draw onto to put anything on the screen
SDL_Surface *SDL_SetVideoMode(width,height,bpp,flags);
//Example: set up a fullscreen double-buffered hardware display surface at 640x480x32
SDL_Surface *screen = SDL_SetVideoMode(640,480,32,SDL_HWSURFACE|SDL_FULLSCREEN|SDL_DOUBLEBUF);
In general, for simple applications, you will want to use the flags as specified in my example (fullscreen optional). This means the surface will be stored in your graphics card's video memory (faster) and it will use an intermediate buffer so the screen is all updated at the same time (smoother). If you are writing a proper application, you will want to use SDL_ListModes and SDL_VideoModeOK to validate the screen mode you are about to enter before doing it. For more information please consult the SDL Documentation
Clearing the screen
There is no built-in command to clear the video surface, so you will have to use the SDL_FillRect command
SDL_FillRect(screen,NULL,SDL_MapRGB(screen->format,0,0,0));
The NULL second parameter means we want to fill the whole screen, not just a part of it, and the MapRGB function will take a triplet of RGB values and return a colour in the surface's compatible format. Here I have used 0,0,0 which represents black, but you can use any combination of values up to 255,255,255
Updating the Display
If you are using a double-buffered video surface, you will need to use the SDL_Flip function to update the physical screen with the contents of your screen buffer. It is very easy to use
SDL_Flip();
Working with graphics
Loading graphics
To load a graphic into a surface that can be displayed on the screen, you will to use the SDL_LoadBMP function. The core SDL library only supports the Windows BMP format, so to use anything else you will need to read up on the SDL_image library
SDL_Surface *my_graphic = SDL_LoadBMP("some_graphic_file.bmp");
This will load "some_graphic_file.bmp" into a a new SDL_Surface pointed to by my_graphic, which you will use when you want to access the surface later (for example to draw it)
Drawing graphics
Drawing graphics to the screen is done by something called a blitter. It is essentially copying one chunk of video memory to another. To do this in SDL you need to use the SDL_BlitSurface function. This is an example of how to use it in it's basic form (to display a graphic on the screen)
SDL_Rect dst;
dst.x=destination_x_position;
dst.y=destination_y_position;
dst.w=my_graphic->w;
dst.h=my_graphic->h;
SDL_BlitSurface(my_graphic,NULL,screen,&dst);
Because this is quite long-winded, you will probably want to put this in some kind of function, like this:
void drawGraphic(SDL_Surface *graphic, int x, int y) {
SDL_Rect dst;
dst.x=x;
dst.y=y;
dst.w=graphic->w;
dst.h=graphic->h;
SDL_BlitSurface(graphic,NULL,screen,&dst);
}
Event Management
The SDL event system lets you look at any events passed to the application. The most useful ones of these are keyboard events and the quit event, which tells you if the operating system is trying to close the program (ie. someone presses the 'x' on the window). This is a simple way to check through the event queue:
[code] SDL_Event e; while (SDL_PollEvent(&e)) { switch (e.type) { case SDL_KEYDOWN: //do something break; case SDL_KEYUP: //do something break; case SDL_QUIT: //quit the program asap break; } } [/code lang=c]As always, a full list of options is available in the SDL Documentation
Shutting down SDL
The SDL_Quit function will deallocate all resources and shut down all subsystems ready to return to the OS. This will work for simple applications, but if you are using some complex resource management system, I recommend you implement a way of freeing all your own resources using SDL_FreeSurface
Putting it all together
A combination of all the above code will leave you with a simple application which initialises the display, draws an image to the screen, then quits when you press escape or click the application's 'x'
#include <SDL/SDL.h>
SDL_Surface *screen;
void drawGraphic(SDL_Surface *graphic, int x, int y) {
//initialize SDL_Rect struct to hold destination blitting data
SDL_Rect dst;
//fill dst with relevant information
dst.x=x;
dst.y=y;
dst.w=graphic->w;
dst.h=graphic->h;
//blit the graphic to the screen
SDL_BlitSurface(graphic,NULL,screen,&dst);
}
int main(int argc, char **argv) {
//declare pointer to reference the graphic (done here for plain C compatibility)
SDL_Surface *my_graphic;
//e stores the event union which is fetched from the event queue
SDL_Event e;
//initialize SDL and the video subsytem
SDL_Init(SDL_INIT_VIDEO);
//set a 640x480x32 double-buffered window
screen = SDL_SetVideoMode(640,480,32,SDL_HWSURFACE|SDL_DOUBLEBUF);
//load the graphic from a file
my_graphic = SDL_LoadBMP("some_graphic_file.bmp");
int running=1;
while (running) {
//clear the screen
SDL_FillRect(screen,NULL,SDL_MapRGB(screen->format,0,0,0));
//draw the graphic
drawGraphic(my_graphic,10,10);
//update the screen
SDL_Flip(screen);
//check the event queue
while (SDL_PollEvent(&e)) {
switch (e.type) {
case SDL_KEYDOWN:
if (e.key.keysym.sym==SDLK_ESCAPE) running=0;
break;
case SDL_QUIT:
running=0;
break;
}
}
}
//deinitialize SDL
SDL_Quit();
return 0;
}
Compile it, put the necessary BMP file in the folder, then run it. You should see the image in a window.
Important note: I have done very little in the way of error checking here, and in a real application you should do a lot more; this is just a simple application to get you started