This tutorial will focus on getting a basic image rendered in the middle of the screen and let the user move it around with the arrow keys of the keyboard. The windows-only function from the first tutorial have been scrapped, making lighter code.
We will stop using silly resolutions from now on and avoid having crappy colour depths. This tutorial uses 800x600 pixels screen resolution with a 32 bit per pixel colour depth. This will allow us to handle 255 layers for each colour: Red, Green, Blue and Alpha. Let's move onto the code...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <SDL/SDL.h>
We declare global variables here just to point them out and make you see what is really needed to render an image on screen. Note that in further tutorials, these variables will be encapsulated so as to have the cleanest code we can. The first new variable we declare is an SDL_Surface *image which is a pointer the the bitmap file that we load into an SDL_Surface. You therefore notice that we will be drawing an SDL_Surface on another SDL_Surface.... (drawing the *image on *screen). This drawing is done via the SDL_BlitSurface() (This performs a fast blit - copy an array of data to a bitmapped array destination - from the source surface to the destination surface)
function. The function takes 4 parameters:
the source SDL_Surface : this is simply the image surface you want to draw
the source SDL_Surface SDL_Rect : we put NULL here because we just want the entire source SDL_rect to be drawn
the target SDL_Surface : in our case, this is always the screen surface
the target SDL_Surface SDL_Rect : we use the SDL_Rect rect variable we created at the top of the code. This lets us specify the offset from the top left corner of the screen at which our image will be rendered. As a result, it simply lets us set our image position on screen...
// Allocate a pointer to an SDL_Surface for the screen buffer
// and for the image we want to load and display on screen.
SDL_Surface *screen = NULL;
SDL_Surface *image = NULL; // We define a global SDL_Rect variable here. I know it isn't clean
// but the only aim here is to point out WHAT has been added
// from the basic tutorial to this one
SDL_Rect rect;
Our init() function start all the SDL components. The section that is really important here is the last part, where we allocate an SDL_surface according to a bitmap image path:
image = SDL_LoadBMP("GDO_El_Kef.bmp");
The SDL_LoadBMP (Load a Windows BMP file into an SDL_Surface. Returns the new surface, or NULL if there was an error) function simply returns an SDL_Surface pointer if it manages to load the target file.
// Function : init() - Params : none
// SDL Initialisation function
// Instead of having a heavy and loaded main function, all the
// setting up of our application is handled here
bool init()
{
// Initialize SDL
if (SDL_Init (SDL_INIT_VIDEO) < 0)
{
printf ("Couldn't initialize SDL: %s\n", SDL_GetError ());
exit (1);
}
atexit (SDL_Quit);
// Set 800x600 32-bits video mode
screen = SDL_SetVideoMode (800, 600, 32, SDL_SWSURFACE | SDL_DOUBLEBUF);
if (screen == NULL)
{
printf ("Couldn't set 800x600 32b video mode: %s\n", SDL_GetError ());
exit (2);
}
// Set the title of our application window handler
SDL_WM_SetCaption ("SDL MultiMedia Application", NULL);
// We now load our first bitmap image.
image = SDL_LoadBMP("GDO_El_Kef.bmp");
if (!image)
{
printf("*** Error attempting to load file: GDO_El_Kef");
exit (3);
}
// This lets us set the original coordinates of our image on the screen.
// Don't forget that top left corner is the origin (0,0)
rect.x = 200;
rect.y = 200;
// We activate <font color='green'><i>keyboard repetition</i></font>. Therefore, when a key stays pressed down
// it will keep moving the image around the screen
// To see prcisely what this toggle does, just comment the line and recompile
// the code...
SDL_EnableKeyRepeat(25, 20);
return true;
}
Not much new stuff here, except the use of the SDL_BlitSurface() function to draw the bitmap where we want on screen.
// Function : draw() - Params : none
// Frame rendering function
// This function is called on every loop, to draw the scene
// It draws then swaps the work and screen buffer to display the scene
void draw ()
{
Uint32 color;
// Create a black background using the screen pixel format (32 bpp)
color = SDL_MapRGB (screen->format, 0, 0, 0);
SDL_FillRect (screen, NULL, color);
// Set the image offset
SDL_BlitSurface(image, NULL, screen, &rect);
// Flip the working image buffer with the screen buffer
SDL_Flip (screen);
// Add a little pause...
SDL_Delay (1);
}
The main() function now handles extra events: Key Presses.
Each time a key is pressed, it is take into account as an event, which is placed in an event queue (Internally, SDL stores all the events waiting to be handled in an event queue. Using functions like SDL_PollEvent, SDL_PeepEvents and SDL_WaitEvent you can observe and handle waiting input events). Each time we iterrate through our game loop, we take the
first event placed in the queue and act accordinly. Event Queue is FIFO (First in first out. The first element to be inserted in the queue will be the first one retrieved) type.
When an arrow key is pressed, we increment or decrement the rect.x and rect.y variables so as to set the new image offset on screen.
// Function : main() - Params : argc, argv
// Main program function
// This function calls the init() function then loops on draw function
// until an escape condition is reached</span>
int main (int argc, char *argv[])
{
// Used to loop
int done = 0;
// The keys variable is used to store the state of the keyboard at
// each frame and see if which keys are pressed down
Uint8 *keys;
// Initialise SDL and all the rest...
init();
// Game Loop
while (!done)
{
// This will let us track events
SDL_Event event;
// We fill 'event' with the first event in the event queue
while (SDL_PollEvent (&event))
{
switch (event.type)
{
// If our event reports a key being pressed down
// we process it
case SDL_KEYDOWN:
keys = SDL_GetKeyState(NULL);
if ( keys[SDLK_LEFT] ) { rect.x--;}
if ( keys[SDLK_RIGHT] ) { rect.x++;}
if ( keys[SDLK_UP] ) { rect.y--;}
if ( keys[SDLK_DOWN] ) { rect.y++;}
if ( keys[SDLK_ESCAPE] ) { done = 1;}
break;
// If the event is a click on the close button in the top
// right corner of the window, we kill the application
case SDL_QUIT:
done = 1;
break;
default:
break;
}
}
// Render the scene
draw ();
}
return 0;
}
Download the tutorial source
HERE