GFXwithSDLPart1.pdf

(295 KB) Pobierz
GFX with SDL
GFX with SDL
Lesson 1: Getting started with SDL
by Marius Andra
Welcome to the first tutorial in the "GFX with SDL" series.
Using SDL with Dev-C++
The first thing you need is to download some files that you will need. They are in
the zip sdlDevCPP.zip (click the name to download). Extract the zip INSIDE your
Dev-C++ directory so that the files from the folders lib and include (from the zip)
get extracted to the folders lib and include in your Dev-C++ directory. On my
computer the Dec-C++ folder is c:\Dev-C++. So after extracting the zip I would
have the files libSDL.a, libSDL.la, libSDLmain.a and SDL.dll inside c:\Dev-C++\lib
and lots of .h files inside c:\Dev-C++\include\SDL.
One important file with SDL is the file SDL.dll. If you would want to run SDL
programs, then you MUST have the file SDL.dll inside c:\windows\system (win
95, 98, ME) or c:\windows\system32 (on windows NT, 2000 and XP). OR you
may have the file SDL.dll in the SAME folder as the executable of your program.
If you would want to distribute your SDL programs among friends then you MUST
also give them the file SDL.dll. SO copy the file SDL.dll from c:\Dev-C++\lib into
c:\windows\system or c:\windows\system32 (on NT, 2000 and XP) on your
system and distribute it with your executables.
Now in Dev-C++ start a new console project. Now go to the project options dialog
(found in the menu Project). The thing we need to set here is the field that says
"Further object files or linker options:". Type in "-lmingw32 -lSDLmain -lSDL" (w/o
the quotes) inside it. Now click OK.
One last thing: when you do printf(...) when having the SDL stuff in the project
options in Dev-C++ the output of printf is written to a file called stdout.txt, not the
screen.
And that's all the Dev-C++ related stuff. In the future I'll probably give you info on
how to get started with different IDE's/compilers
Getting started with SDL
You are basically all set. You only need to add the include file SDL/SDL.h to the
top of your program like this:
#include < SDL/SDL . h >
Initializing SDL is done through the SDL_Init() function. SDL_Init returns
less than 0 on failure. It takes one parameter: what to initialize. To initialize the
1
video screen pass to it the constant SDL_INIT_VIDEO . To initialize the audio,
pass to it the constant SDL_INIT_AUDIO . To initialize the video and audio, pass
to it SDL_INIT_VIDEO|SDL_INIT_AUDIO . There are many more things that
you can pass (separating them with |'s when passing many at once). Here are
the things you can pass:
SDL_INIT_TIMER
SDL_INIT_AUDIO
SDL_INIT_VIDEO
SDL_INIT_CDROM
SDL_INIT_JOYSTICK
SDL_INIT_NOPARACHUTE
SDL_INIT_EVENTTHREAD
SDL_INIT_EVERYTHING
So in conclusion if we would want to init the video and the audio we get:
if( SDL_Init ( SDL_INIT_VIDEO|SDL_INIT_AUDIO ) < 0 )
{
printf ( "Unable to init SDL: %s\n" , SDL_GetError ());
}
return 1 ;
If an error occurred, then the function SDL_GetError() would return a string
about the error.
When exiting your C++ program, you must execute the function SDL_Quit() .
That will clear up everything. If you wouldn't execute it before exiting your
program, strange things may occur. To tell the compiler that you want to run
SDL_Quit on exit, tell it like this:
atexit ( SDL_Quit );
That way you don't need to put SDL_Quit() before every return [nr]; in main() .
In SDL you have many surfaces. Everything is a surface. You can draw on a
surface and you can also draw a surface on an other surface. In SDL the screen
is also a surface. A surface in our program is actually a pointer to the structure
SDL_Surface . To get the screen surface do this:
SDL_Surface *screen ;
I'm sure you have seen at some point in your life that some game asked you for a
screen resolution to run at. If not, well then PLAY MORE GAMES. If you would
want to use the surface screen (remember, screen is just the name of a pointer
to the structure SDL_Surface ) as the surface you can draw on (and you will see
what you have drawn on your monitor) then use the function
SDL_SetVideoMode() :
2
screen = SDL_SetVideoMode ( 640 , 480 , 32 ,
SDL_HWSURFACE|SDL_DOUBLEBUF );
The first three parameters are the width, height and bits per pixel of the screen. If
you type in 0 for the BPP then SDL would automatically select the best available
BPP. The fourth parameter is used to give some special flags. You must (almost)
always give it SDL_HWSURFACE (or SDL_SWSURFACE ) if you want a screen to
draw on. Here's a list of what you may give it:
SDL_SWSURFACE - Create the video surface in system memory
SDL_HWSURFACE - Create the video surface in video memory
SDL_ASYNCBLIT - Enables the use of asynchronous updates of the display
surface. This will usually slow down blitting on single CPU machines, but may
provide a speed increase on SMP systems.
SDL_ANYFORMAT - Normally, if a video surface of the requested bits-per-pixel
(bpp) is not available, SDL will emulate one with a shadow surface. Passing
SDL_ANYFORMAT prevents this and causes SDL to use the video surface,
regardless of its pixel depth.
SDL_HWPALETTE - Give SDL exclusive palette access. Without this flag you may
not always get the colors you request with SDL_SetColors or SDL_SetPalette.
SDL_DOUBLEBUF - Enable hardware double buffering; only valid with
SDL_HWSURFACE . Calling SDL_Flip will flip the buffers and update the screen. All
drawing will take place on the surface that is not displayed at the moment. If
double buffering could not be enabled then SDL_Flip will just perform a
SDL_UpdateRect on the entire screen.
SDL_FULLSCREEN - SDL will attempt to use a fullscreen mode. If a hardware
resolution change is not possible (for whatever reason), the next higher
resolution will be used and the display window centered on a black background.
SDL_OPENGL - Create an OpenGL rendering context. You should have
previously set OpenGL video attributes with SDL_GL_SetAttribute.
SDL_OPENGLBLIT - Create an OpenGL rendering context, like above, but allow
normal blitting operations. The screen (2D) surface may have an alpha channel,
and SDL_UpdateRects must be used for updating changes to the screen
surface.
SDL_RESIZABLE - Create a resizable window. When the window is resized by
the user a SDL_VIDEORESIZE event is generated and SDL_SetVideoMode can
be called again with the new size.
SDL_NOFRAME - If possible, SDL_NOFRAME causes SDL to create a window with
no title bar or frame decoration. Fullscreen modes automatically have this flag
set.
My recommendation: give it SDL_HWSURFACE|SDL_DOUBLEBUF and in case of
an error try again with SDL_SWSURFACE .
3
SDL_SetVideoMode returns a pointer to SDL_Surface if successful or NULL if
not. To check for errors use this block of code:
if ( screen == NULL )
{
printf ( "Unable to set 640x480 video: %s\n" , SDL_GetError ());
}
return 1 ;
And that's all about initializing SDL. You can now start drawing. But before we
get into drawing stuff I'll tell you about some new data types that SDL gave us so
you don't get confused when you run into them. They are:
Uint8 - the equivalent of an unsigned char
Uint16 - a 16 bit (2 byte) unsigned integer
Uint32 - a 32 bit (4 byte) unsigned integer
Uint64 - a 64 bit (8 byte) unsigned integer
Sint8 - the equivalent of a signed char
Sint16 - a 16 bit (2 byte) signed integer
Sint32 - a 32 bit (4 byte) signed integer
Sint64 - a 64 bit (8 byte) signed integer
And one more thing: Sometimes when you get errors on initializing stuff you don't
need to exit completely. For example when initializing SDL_INIT_VIDEO passed
and SDL_INIT_AUDIO did not, you can still continue with the program, only
without audio. To check (for example) if the audio initialization succeeded, use
the SDL_WasInit() function. Here's some code:
Uint32 init = SDL_WasInit
if( init & SDL_INIT_AUDIO )
( SDL_INIT_AUDIO );
{
soun =
} else {
d 1 ; // Audio init successful, use sound
sound = 0 ; // Audio init unsuccessful, don't use sound
}
You should add the code somewhere between the
if( SDL_Init ( SDL_INIT_VIDEO|SDL_INIT_AUDIO ) < 0 )
{
printf ( "Unable to init SDL: %s\n" , SDL_GetError ());
return 1 ;
}
code in your own programs (I won't add it in the tutorials (for now) for simplicity).
Drawing pixels isn't very easy at first, but when you have a function that does it
for you it can't get any easier. The function that I use for drawing pixels is taken
from the SDL intro (found on www.libsdl.org). It looks like this:
NOTE: you don't need to understand all of it. Just know that it works:
4
void DrawPixel ( SDL_Surface *screen , int x , int y ,
Uint8 R , Uint8 G , Uint8 B )
{
Uint32 color = SDL_MapRGB ( screen- > format , R , G , B );
switch ( screen- > format- > BytesPerPixel )
{
case 1: // Assuming 8-bpp
{
Uint8 *bufp ;
bufp = ( Uint8 * ) screen- > pixels + y*screen- > pitch + x ;
*bufp = color ;
}
break;
case 2: // Probably 15-bpp or 16-bpp
{
Uint16 *bufp ;
bufp = ( Uint16 * ) screen- > pixels + y*screen- > pitch/2 + x ;
*bufp = color ;
}
break;
case 3: // Slow 24-bpp mode, usually not used
{
Uint8 *bufp ;
bufp = ( Uint8 * ) screen- > pixels + y*screen- > pitch + x * 3 ;
if( SDL_BYTEORDER == SDL_LIL_ENDIAN )
{
bufp [ ]
case 4: // Probably 32-bpp
{
Uint32 *bufp ;
bufp = ( Uint32 * ) screen- > pixels + y*screen- > pitch/4 + x ;
*bufp = color ;
}
break;
}
}
You pass it the surface you want to draw on, the x and y of the point and the
RGB of the color you want to draw the point in.
The following paragraph is a crash course in RGB. Don't read it if you don't want
to.
Look at your monitor very closely with a magnifying glass (note: you may hurt
your eyes if you do it a lot). Look at some white part of the screen. You will see
5
0 = color
bufp [ 1 ] = color >> 8 ;
bufp [ 2 ] = color >> 16 ;
} else {
bufp [ 2 ] = color ;
bufp [ 1 ] = color >> 8 ;
bufp [ 0 ] = color >> 16 ;
}
}
break;
;
Zgłoś jeśli naruszono regulamin