GFX with SDLLesson 1: Getting started with SDL Author: Marius Andra translation: heroboy
Welcome to the first tutorial of "GFX with SDL". Use SDL in DEV-C First you first need to download SDLDEVCPP 1.2.4.zip (click on Name Download). Differentize the ZIP file to the DEV C directory, make sure the files in the include and Lib folders (in the zip file) are extracted into the include and lib folders in DEV C . The DEV-C folder on my computer is C: / DEV-C . So after decompression, there will be libsdl.a, libsdl.la, libsdlmain.a, libsdl.la, libsdlmain.a, and sdl.dll in C: / DEV-C / Include / SDL .h file.
Now, create a console project in DEV-C . Open the Engineering Properties dialog box (in the Project "menu). In the parameter, click the "Add" to the Library or Object "button, select three files for libsdl.a, sdlmain.a and ligmingw32.a. Click "OK".
Finally, use printf (...) or output to stdout.txt in the SDL project, not the screen.
Use SDL to use SDL in MSVC6 in MSVC6 to download SDL-devel 1.2.4-vc6.zip (please visit www.libsdl.org download updated SDL) in Microsoft Visual C 6.0. There are two important folders -Include and libs in this compressed file, copy files in the lib folder into the Lib folder of MSVC6 (on my machine is C: / Program Files / Microsoft Visual Studio / VC98 / Lib), create a new SDL folder in the INCLUDE folder of the MSVC6 (on my machine is C: / Program Files / Microsoft Visual Studio / VC98 / INCLUDE / SDL), in the Include folder in the compressed file. The H file is copied to the new folder.
Now, create a new project in VC . Select "Win32 Application" and "'An Empty Project". Now you have to create a CPP file for the project, click File-> New and select "C Source File", the name enters "main.cpp". Turn on the Engineering Options dialog (Menu Project-> Settings). Click on the "Link" column to add "SDL.LIB SDLMain.LIB" to the connection file (Object / library modules). Finally, click the "C / C " column to select "Code Generation" in the drop-down menu. Then select "Multithreaded DLL" in the "Use Run-Time Library drop-down box.
SDL.dll
SDL.dll is an important file in SDL (it in the SDL ZIP file of DEV-C or MSVC6). If you want to run an SDL program, you must copy SDL.dll to C: / Windows / System (WIN 95, 98, ME) or C: / Windows / System32 (ON Windows NT, 2000 and XP). Or SDL.DLL and your program are in the same folder. Getting Started with SDL You have already set up everything. You have to include SDL / SDL.h files in your program as follows:
#include
The SDL is initialized by the SDL_INIT () function. The return value of SDL_INIT indicates an error at 0. It accepts a parameter and initialized content. SDL_INIT_VIDEO initializes video, SDL_INIT_AUDIO initializes the audio. To initialize audio and video, use SDL_INIT_VIDEO | SDL_INIT_AUDIO. You can initialize more items (to initialize at the same time):
SDL_INIT_TIMER
SDL_INIT_AUDIO
SDL_INIT_VIDEO
SDL_INIT_CDROM
SDL_INIT_JOYSTICK
SDL_INIT_NOPARECHUTE
SDL_INIT_EVENTTHREAD
SDL_INIT_EVERYTHING
Therefore, the code initialized video and audio is:
IF (SDL_INIT (SDL_INIT_VIDEO | SDL_INIT_AUDIO) <0)
{
Printf ("Unable to INIT SDL:% S / N", SDL_GETERROR ());
Return 1;
}
If an error occurs, the SDL_GETERROR () function returns a string to describe this error.
But when you exit the program, you must call SDL_QUIT (). If there is no call, some exceptions may occur. Tell the compiler that you want to call SDL_QUIT when you exit, the code is as follows:
Atexit (SDL_QUIT);
That don't need to add SDL_QUIT () before each Return in the main function. There is a need for many Surface in SDL. Everything is Surface. You can draw on Surface or draw a Surface to another Surface. In SDL, the screen is also a SURFACE. In our program, Surface is a pointer to the SDL_SURFACE structure. Get the screen Surface:
SDL_SURFACE * Screen;
I believe that you will choose the screen resolution when you play some games. If you have not, please play more games. If you want to use the Surface screen (Remember, Screen is just a pointer to the SDL_SURFACE structure), drawing above (what you can see on the monitor), then use the SDL_setVideoOde () function.
Screen = SDL_SETVIDEOMODE (640, 480, 32,
SDL_HWSURFACE | SDL_DOUBLEBUF);
The top three parameters are the width, height, and pixel bits bits per pixel of the screen, respectively. If the number of pixel bit is 0, SDL will automatically select the most suitable number of bits for you. The fourth parameter is some special tags. If you want to draw pictures on the screen, you must have SDL_HWSURFACE (or SDL_swsurface). The following is available:
SDL_swsurface - Creating Surface SDL_HWSurface in System Memory - Creating Surface SDL_ASYNCBLIT in the display memory - Allow asynchronous refresh Surface. This reduces the speed of blitting (Blitting) on a single CPU, but speeds up on the SMP system. SDL_AnyFormat - Generally, if the pixel bit number (Bits-PIXEL, BPP) is not available, SDL returns the shadow Surface (Shadow Surface). SDL_AnyFormat prevents this, and ignores the number of pixel positions in the parameters. SDL_HWPALETTE - Give SDL independent palette access (Exclusive Palette Access). Without this option, you can't get colors through SDL_SETCOLORS or SDL_SETPALETTE. SDL_DOUBLEBUF - Allows hardware double buffering. It is valid only with SDL_HWSURFACE. Call SDL_FLIP to flip (FLIP) buffer and refresh the screen. All drawings do not appear immediately on the screen. If double buffer is not allowed, the SDL_FLIP function is equivalent to calling SDL_UPDATERECT for the entire screen. SDL_FULLSCREEN - SDL will try to use full screen mode. If the hardware does not support the current resolution, a higher resolution and black background are used. SDL_opengl - Create OpenGL Rendering Context. You should use SDL_GL_SetAttribute to set the OpenGL video properties in advance. SDL_openglblit - Create OpenGL Rendering Context, but uses a normal bit copy (Blitting). The screen Surface (2D) has an alpha channel and must use SDL_UPDATERECTS to update the screen Surface. SDL_RESIZABLE - Create a scalable window. When zooming, the SDL_VIDEORSIZE event will be generated, and the screen Surface size can be changed again via SDL_SETVIDEOMODE. SDL_NOFRAME - If it is feasible, SDL creates a window without a frameless-free bar. The full screen mode automatically contains this option. My suggestion is: use SDL_HWSURFACE | SDL_DOUBLEBUF. If you go wrong, use SDL_swsurface.sdl_setVideomode to return to the pointer to the SDL_Surface, and return null. Use the following code to detect an error: if (Screen == Null)
{
Printf ("Unable to set 640x480 video:% s / n", SDL_GETERROR ());
Return 1;
}
The SDL has been initialized to start drawing. Before starting the drawing, I want to tell you some of the SDL data types. they are:
UINT8 - equivalent to unsigned char
UINT16 - 16-bit (2 bytes) unsigned shaping
UINT32 - 32-bit (4 bytes) unsigned shaping
UINT64 - 64-bit (8 bytes) unsigned shaping
SINT8 - equivalent to Signed Char
SINT16 - 16-bit (2 bytes) Symbolic shaping
SINT32 - 32-bit (4 bytes) with symbolic shaping
SINT64 - 64-bit (8 bytes) Symbolic shaping
In addition, you don't have to completely exit whenever you initialize an error. For example, SDL_INIT_VIDEO is initialized, while SDL_INIT_AUDIO failed, you can still continue to run the program, just no sound. In order to detect whether the audio is initialized, use the SDL_WASINIT () function. The code is as follows: uint32 init = SDL_WASINIT (SDL_INIT_AUDIO);
IF (Init & SDL_INIT_AUDIO)
{
Sound = 1; // Audio Init Sucessful, Use Sound
} else {
Sound = 0; // Audio Init Unsucessful, Don't Uses
}
You can insert the above code in the following code
IF (SDL_INIT (SDL_INIT_VIDEO | SDL_INIT_AUDIO) <0)
{
Printf ("Unable to INIT SDL:% S / N", SDL_GETERROR ());
Return 1;
}
For simplicity, I don't insert this code in the tutorial. Drawing pixels is very simple, but if you see this function, it is not simple. This pixel, which I use, taken from SDL INTRO (www.libsdl.org). as follows:
Note: You don't have to fully understand it, just use it.
Void Drawpixel (SDL_SURFACE * Screen, INT X, INT Y,
Uint8 r, uint
8 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 [0] = Color;
BUFP [1] = Color >> 8;
BUFP [2] = Color >> 16;
} else {
BUFP [2] = Color;
BUFP [1] = Color >> 8;
BUFP [0] = Color >> 16;
}
}
Break;
Case 4: // probably 32-bpp
{
Uint32 * bufp;
BUFP = (uint32 *) Screen-> Pixels Y * screen-> PITCH / 4 X;
* bufp = color;
}
Break;
}
}
Passing a Surface, x-axis, y-axis coordinates, and RGB colors you want to draw. There are also two important functions. Some graphics cards need to be locked in front of the drawing. SDL_Mustlock (SDL_SURFACE * screen) is used to determine if a lock screen is required. SDL_LOCKSURFACE (SDL_SURFACE * Screen) and SDL_UNLOCKSURFACE (SDL_SURFACE * Screen) are used to lock and unlock. The function code is as follows:
Void Slock (SDL_SURFACE * Screen)
{
IF (SDL_Mustlock (SCREEN))
{
IF (SDL_LOCKSURFACE (SCREEN) <0)
{
Return;
}
}
}
Void Sulock (SDL_SURFACE * Screen)
{
IF (SDL_Mustlock (SCREEN))
{
SDL_Unlocksurface (screen);
}
}
Call the Slock (Screen) Lock Screen, Sulock (Screen) unlocks. Now, the code should be as follows:
#include
#include
#include
// the functions area not shown to save space
Void Drawpixel (SDL_SURFACE * Screen, INT X, INT Y,
Uint8 r, uint
8 g
UINT8 B);
Void Slock (SDL_SURFACE * Screen);
Void Sulock (SDL_SURFACE * Screen);
Int main (int Argc, char * argv [])
{
IF (SDL_INIT (SDL_INIT_AUDIO | SDL_INIT_VIDEO) <0)
{
Printf ("Unable to INIT SDL:% S / N", SDL_GETERROR ());
Exit (1);
}
Atexit (SDL_QUIT);
SDL_SURFACE * Screen;
Screen = SDL_SETVIDEOMODE (640, 480, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
IF (screen == null)
{
Printf ("Unable to set 640x480 video:% s / n", SDL_GETERROR ());
Exit (1);
}
// Drawing Goes Here
Return 0;
}
Run. You will find that an empty window flashes. Join the SDL_FULLSCREEN tag, you will see a black screen. Now let us draw.
Let's do a simple drawing: We draw all things on a buffer and put the bughket to the screen. This is simpler with simplicity directly on the screen, fast speed, and no flashes.
Let us be a colored screen (as shown in the screenshot). We draw all coordinates through a loop. Add a function of the lock screen to the cycle, add a unlocked function after the loop. The DrawPixel function draws colorful pixels (different) on the screen Surface (Different colors), then use SDL_FLIP to draw buffers to actual computer screens.
Slock (screen);
For (int x = 0; x <640; x )
{
FOR (int y = 0; y <480; y ) {
Drawpixel (Screen, X, Y, Y / 2, Y / 2, X / 3);
}
}
Sulock (screen);
SDL_FLIP (Screen);
Note: It is actually drawn on the screen to draw pixels very slow. Usually, only a part of the need is only drawn when needed. More, please see the tutorial. Replace the // Drawing Goes Here with the above code and allow the program. You will see a colored window, but there is only a short time. In order to have a point longer, add a loop:
For (i = 0; i <100; i )
{
Slock (screen);
For (int x = 0; x <640; x )
{
For (int y = 0; y <480; y )
{
Drawpixel (Screen, X, Y, Y / 2, Y / 2, X / 3);
}
}
Sulock (screen);
SDL_FLIP (Screen);
}
Loop 100 times, then exit. But there is a better way: we put the drawing code in a function:
Void DrawScene (SDL_SURFACE * Screen)
{
Slock (screen);
For (int x = 0; x <640; x )
{
For (int y = 0; y <480; y )
{
Drawpixel (Screen, X, Y, Y / 2, Y / 2, X / 3);
}
}
Sulock (screen);
SDL_FLIP (Screen);
}
In the main () function, we create a game loop. The game loop is a loop until it exits. Our game loop is a while loop that loops when Done is equal to 0.
INT DONE = 0;
While (DONE == 0)
{
// Code
}
In the game loop, we detect if the ESC key or the X button on the window is pressed. If you press it, let DONE is equal to 1, then the loop will end. Everything SDL events are represented using the SDL_Event structure. We need a SDL_Event variable to detect time:
SDL_EVENT EVENT;
We have not stopped incident (until there is no incident):
While (SDL_POLLEVENT (& Event))
{
}
In each while (...) {...}, SDL_Event will contain information information. Then we determine the type of event.
IF (event.type == sdl_quit) {done = 1;}
IF (event.type == SDL_KEYDOWN)
{
// Code
}
If we get an exit event (close button is pressed), we will make DONE equal to 1. If a button is pressed, we are determined which key is pressed:
IF (event.key.keysym.sym == sdlk_escape) {done = 1;}
The key name on all keyboard is started with SDLK_. View the SDL_Keysym.h file to get more SDLK_ key names. After the event detection:
Drawscene (Screen);
Ok, the following is all code:
#include
#include
#include
Void Slock (SDL_SURFACE * Screen)
{
IF (SDL_Mustlock (SCREEN))
{
IF (SDL_LOCKSURFACE (SCREEN) <0)
{
Return;
}
}
}
Void Sulock (SDL_SURFACE * Screen)
{
IF (SDL_Mustlock (SCREEN))
{
SDL_Unlocksurface (screen);
}
}
Void Drawpixel (SDL_SURFACE * Screen, INT X, INT Y,
Uint8 r, uint
8 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 [0] = Color;
BUFP [1] = Color >> 8;
BUFP [2] = Color >> 16;
} else {
BUFP [2] = Color;
BUFP [1] = Color >> 8;
BUFP [0] = Color >> 16;
}
}
Break;
Case 4: // probably 32-bpp
{
Uint32 * bufp;
BUFP = (uint32 *) Screen-> Pixels Y * screen-> PITCH / 4 X;
* bufp = color;
}
Break;
}
}
Void DrawScene (SDL_SURFACE * Screen)
{
Slock (screen);
For (int x = 0; x <640; x )
{
For (int y = 0; y <480; y )
{
Drawpixel (Screen, X, Y, Y / 2, Y / 2, X / 3);
}
}
Sulock (screen);
SDL_FLIP (Screen);
}
Int main (int Argc, char * argv [])
{
IF (SDL_INIT (SDL_INIT_AUDIO | SDL_INIT_VIDEO) <0)
{
Printf ("Unable to INIT SDL:% S / N", SDL_GETERROR ());
Exit (1);
}
Atexit (SDL_QUIT);
SDL_SURFACE * Screen;
Screen = SDL_SETVIDEOMODE (640, 480, 32, SDL_HWSURFACE | SDL_DOUBLEBUF); if (Screen == Null)
{
Printf ("Unable to set 640x480 video:% s / n", SDL_GETERROR ());
Exit (1);
}
INT DONE = 0;
While (DONE == 0)
{
SDL_EVENT EVENT;
While (SDL_POLLEVENT (& Event))
{
IF (event.type == sdl_quit) {done = 1;}
IF (event.type == SDL_KEYDOWN)
{
IF (event.key.keysym.sym == sdlk_escape) {done = 1;}
}
}
Drawscene (Screen);
}
Return 0;
}