By Tony and Paige at www.tonyandpaige.com
After my 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.
- The program starts of just like the first example, SDL is initialized, the window is created, etc.
- 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.
- The program then continues as before. The background is loaded, and we enter the main loop.
- 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.
- 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.
- 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.
- Next the for loop blits the background tile all over the screen.
- Then the sprite is drawn over the background.
- 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.cpp, or sdlmove.c if you'd like to use straight C instead of 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"
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
#define SPRITE_SIZE 32
int main ( int argc, char *argv[] )
{
SDL_Surface *screen, *temp, *sprite, *grass;
SDL_Rect rcSprite, rcGrass;
SDL_Event event;
Uint8 *keystate;
int colorkey, gameover;
/* initialize SDL */
SDL_Init(SDL_INIT_VIDEO);
/* set the title bar */
SDL_WM_SetCaption("SDL Move", "SDL Move");
/* create window */
SDL_Surface* 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 */
rcSprite.x = 0;
rcSprite.y = 0;
gameover = 0;
/* message pump */
while (!gameover)
{
/* 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;
}
break;
}
}
/* handle sprite movement */
keystate = SDL_GetKeyState(NULL);
if (keystate[SDLK_LEFT] ) {
rcSprite.x -= 2;
}
if (keystate[SDLK_RIGHT] ) {
rcSprite.x += 2;
}
if (keystate[SDLK_UP] ) {
rcSprite.y -= 2;
}
if (keystate[SDLK_DOWN] ) {
rcSprite.y += 2;
}
/* collide with edges of screen */
if ( rcSprite.x < 0 ) {
rcSprite.x = 0;
}
else if ( rcSprite.x > SCREEN_WIDTH-SPRITE_SIZE ) {
rcSprite.x = SCREEN_WIDTH-SPRITE_SIZE;
}
if ( rcSprite.y < 0 ) {
rcSprite.y = 0;
}
else if ( rcSprite.y > SCREEN_HEIGHT-SPRITE_SIZE ) {
rcSprite.y = SCREEN_HEIGHT-SPRITE_SIZE;
}
/* draw the grass */
for (int x = 0; x < SCREEN_WIDTH / SPRITE_SIZE; x++) {
for (int y = 0; y < SCREEN_HEIGHT / SPRITE_SIZE; y++) {
rcGrass.x = x * SPRITE_SIZE;
rcGrass.y = y * SPRITE_SIZE;
SDL_BlitSurface(grass, NULL, screen, &rcGrass);
}
}
/* draw the sprite */
SDL_BlitSurface(sprite, NULL, screen, &rcSprite);
/* 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:
g++ sdlmove.cpp `sdl-config --cflags --libs` -o sdlmove |
Then run the program by typing:
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
In Visual C++ you'll need to follow these steps:
- Create a new Win32 Application Project (not a Console Application).
- Add the "sdlmove.cpp" file to your project.
- Go to Project, Settings and click the C/C++ tab.
- Beside Catagory, choose Code Generation.
- Under Use run-time library, choose Multithreaded DLL.
- Now click the Link tab.
- Add SDLmain.lib and SDL.lib to the list of Object/library modules.
- At this point, you should be able to press F7 to Build the program.
Before we can run the program, you'll need to put the "SDL.dll" file where Windows can find it. Copy the file from "C:\Program Files\SDL-1.2.5" to your new Visual C++ project's folder. If your program compiled without errors, you can now press F5 to execute the program.
Downloads
- sdlmove.zip - Tutorial Source, Graphics, and Project files for Visual C++ 6 on Windows.
- sdlmove.tar.gz - Tutorial Source, Graphics, and Makefile for Linux.
This is the next step in learning SDL. You should now be able to create simple games with moving sprites. If you have a suggestion about what I should cover next, e-mail me and let me know. I'm open for ideas. |