After the first SDL tutorial, you should have a pretty good idea of how to set up SDL and display an image on the screen. The next logical step is to read from the keyboard and make something move around on the screen.

This program builds on the example from tutorial 1 in a couple of places, so if you haven't read it yet, or if you're not clear on the basics of SDL, now's a good time to go check it out.

The Moving Sprite Program

Here's a breakdown of what's happening in this sample program.

  1. The program starts of just like the first example, SDL is initialized, the window is created, etc.
  2. The first difference is loading the sprite, not only do we convert the sprite to the display format, we also set a color key. This means that anything in the image that is purple (255, 0, 255), will be treated as transparent.
  3. The program then continues as before. The background is loaded, and we enter the main loop.
  4. After we check for events, we get the current state of the keyboard with SDL_GetKeyState(). This function returns a pointer to an array data describing each key on the keyboard. If a key is pressed, the array will contain a 1, otherwise it will contain 0.
  5. The keystate array is then tested for each of the arrow keys. If any arrow key is pressed, we will move the sprite in that direction.
  6. Now that things are moving, we must test to see if we've moved off the edge of the screen. If so, the sprite is moved back.
  7. Next the for loop blits the background tile all over the screen.
  8. Then the sprite is drawn over the background.
  9. The program ends as before, we free the memory for the surfaces with SDL_FreeSurface, and cleanup SDL with SDL_Quit().

Save this file as sdlmove.c. You'll also need the bitmap files that go with this program. They're available for download with the source code at the bottom of this page.

#include <SDL.h>

/* Size of the window */
#define SCREEN_WIDTH  640
#define SCREEN_HEIGHT 480
/* Size of the sprite; this is a square */
#define SPRITE_SIZE   32
/* Size of the grass texture picture */
#define GRASS_SIZE    32

int main(int argc, char* argv[])
{
    SDL_Surface *screen, *temp, *sprite, *grass;
    SDL_Rect spritePosition;
    int colorkey, gameover;

    /* initialize video system */
    SDL_Init(SDL_INIT_VIDEO);

    /* set the title bar */
    SDL_WM_SetCaption("SDL Move", "SDL Move");

    /* create window */
    screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);

    /* load sprite */
    temp   = SDL_LoadBMP("sprite.bmp");
    sprite = SDL_DisplayFormat(temp);
    SDL_FreeSurface(temp);

    /* setup sprite colorkey and turn on RLE */
    colorkey = SDL_MapRGB(screen->format, 255, 0, 255);
    SDL_SetColorKey(sprite, SDL_SRCCOLORKEY | SDL_RLEACCEL, colorkey);

    /* load grass */
    temp  = SDL_LoadBMP("grass.bmp");
    grass = SDL_DisplayFormat(temp);
    SDL_FreeSurface(temp);

    /* set sprite position */
    spritePosition.x = 0;
    spritePosition.y = 0;

    gameover = 0;

    /* main loop: check events and re-draw the window until the end */
    while (!gameover)
    {
        SDL_Event event;
        Uint8 *keystate;

        /* look for an event */
        if (SDL_PollEvent(&event)) {
            /* an event was found */
            switch (event.type) {
                /* close button clicked */
                case SDL_QUIT:
                    gameover = 1;
                    break;

                /* handle the keyboard */
                case SDL_KEYDOWN:
                    switch (event.key.keysym.sym) {
                        case SDLK_ESCAPE:
                        case SDLK_q:
                            gameover = 1;
                            break;
                        default:
                            break;
                    }
                    break;
            }
        }

        /* handle sprite movement */
        keystate = SDL_GetKeyState(NULL);

        if (keystate[SDLK_LEFT] ) {
            spritePosition.x -= 2;
        }
        if (keystate[SDLK_RIGHT] ) {
            spritePosition.x += 2;
        }
        if (keystate[SDLK_UP] ) {
            spritePosition.y -= 2;
        }
        if (keystate[SDLK_DOWN] ) {
            spritePosition.y += 2;
        }

        /* collide with edges of screen */
        if (spritePosition.x < 0) {
            spritePosition.x = 0;
        } else if (spritePosition.x > SCREEN_WIDTH - SPRITE_SIZE) {
            spritePosition.x = SCREEN_WIDTH - SPRITE_SIZE;
        }

        if (spritePosition.y < 0) {
            spritePosition.y = 0;
        } else if (spritePosition.y > SCREEN_HEIGHT - SPRITE_SIZE) {
            spritePosition.y = SCREEN_HEIGHT - SPRITE_SIZE;
        }

        /* map the grass texture on the whole background */
        for (int x = 0; x < SCREEN_WIDTH/GRASS_SIZE; x++) {
            for (int y = 0; y < SCREEN_HEIGHT/GRASS_SIZE; y++) {
                SDL_Rect position;
                position.x = x * GRASS_SIZE;
                position.y = y * GRASS_SIZE;
                SDL_BlitSurface(grass, NULL, screen, &position);
            }
        }

        /* draw the sprite */
        SDL_BlitSurface(sprite, NULL, screen, &spritePosition);

        /* update the screen */
        SDL_UpdateRect(screen,0,0,0,0);
    }

    /* clean up */
    SDL_FreeSurface(sprite);
    SDL_FreeSurface(grass);
    SDL_Quit();

    return 0;
}

Note, there is no error checking in this program. If something fails, it will be hard to track down. I left out the error checking just to make the program shorter and easier to follow. In a real program you should check the return values of all the SDL function calls.

Compiling

On Linux you can compile this program by typing this command:

gcc -Wall -g -std=c99 sdlmove.c `sdl-config --cflags --libs` -o sdlmove

Then run the program by typing:

./sdlmove

If everything worked correctly, a 640x480 window should open with a field of grass and a small sprite that you can move with the keyboard

Downloads