From the translator: inspired by a series of articles , I decided to try my hand at SDL. Yes, that's bad luck, I could not find any sensible lessons on SDL version 2.0 in Russian. This prompted me to translate a wonderful series of Twinklebear tutorials, originally available here .
Welcome!
The purpose of these lessons is to introduce you to the basics of SDL 2.0 and C ++ game maiden. It is understood that the reader has some C ++ programming experience and minimal knowledge of arrays, vectors, control structures, functions, and pointers.
If you are having trouble parsing the code in the examples, use one of the books on this wonderful list on
StackOverflow .
')
If you want to see the full source or download the resources for lessons, then all this can be obtained on
GitHub 'e. But do not copy!
SDL 2.0 documentation is also available for reading on
this wiki .
Lesson 1: Hello World!
In this tutorial, we will learn how to open a window, create a rendering context, and draw a loaded image on the screen. Below you can pick up the BMP image that we will draw. Save it somewhere in your project. So let's get started!
Start SDL
The first step is usually to include the SDL header file.
#include <SDL2/SDL.h>
In order to start working with SDL, we need to initialize the various SDL subsystems we want to use. This can be done using the
SDL_Init function, which accepts a set of
flags indicating which subsystems we want to initialize. Now we just say that we want to initialize everything, but if you want, you can change it. The minimum that is necessary for our lesson is SDL_INIT_VIDEO. If everything goes well, SDL_Init returns 0, otherwise we will print an error and exit.
Note for Visual Studio users: if you set the value of the system as Windows in the linker settings, then you will not get the standard output in the console. To avoid this, you need to change the value of the system to the Console.
if (SDL_Init(SDL_INIT_EVERYTHING) != 0){ std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl; return 1; }
Opening window
We need a window so that it can be displayed on the render. We can create it using the
SDL_CreateWindow function, which takes a window name, its coordinates, height, width, and some
flags to set window parameters. This function returns SDL_Window *. This pointer will be NULL if something goes wrong when creating the window.
SDL_Window *win = SDL_CreateWindow("Hello World!", 100, 100, 640, 480, SDL_WINDOW_SHOWN); if (win == nullptr){ std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl; return 1; }
Creating a renderer
Now we can create a renderer using
SDL_CreateRenderer . This is necessary in order to be able to draw in the window. This function takes a pointer to the window with which you want to associate the renderer, the index of the driver that will be used for rendering (or -1 to select the first one that matches our requirements) and various
flags that use to indicate the type of renderer we need. In this case, we are requesting a hardware accelerated renderer with vertical sync enabled. We will get SDL_Renderer *, which will be NULL if something went wrong.
SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); if (ren == nullptr){ std::cout << "SDL_CreateRenderer Error: " << SDL_GetError() << std::endl; return 1; }
BMP image loading
In order to render a BMP image, we need to first load it into memory, and then into the rendering device that we use (in this case, the GPU). We can load an image using
SDL_LoadBMP . This function returns an
SDL_Surface * , which we can load into
SDL_Texture , so that the renderer can use it.
SDL_LoadBMP takes the path to our image, which you must change to fit the structure of your project, and returns SDL_Surface * or NULL in case of an error.
SDL_Surface *bmp = SDL_LoadBMP("../res/Lesson1/hello.bmp"); if (bmp == nullptr){ std::cout << "SDL_LoadBMP Error: " << SDL_GetError() << std::endl; return 1; }
Now we can load the image into the renderer using the
SDL_CreateTextureFromSurface . We pass the rendering context and image in memory (SDL_Surface), and get the loaded texture. In case something went wrong, we get NULL. Also, SDL_Surface is no longer needed, so we will free the memory it occupies.
SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, bmp); SDL_FreeSurface(bmp); if (tex == nullptr){ std::cout << "SDL_CreateTextureFromSurface Error: " << SDL_GetError() << std::endl; return 1; }
Texture drawing
All that's left to do is get our texture on the screen! First we will
clean the renderer, then
render the texture , and then
show the updated screen to see the result. Since we want to render the entire image and make it stretch to fit the screen, we will pass NULL as the source and target rectangles for SDL_RenderCopy. We also want to keep the window open for a while in order to see the result until the program ends, so we will add the
SDL_Delay call.
SDL_RenderClear(ren); SDL_RenderCopy(ren, tex, NULL, NULL); SDL_RenderPresent(ren); SDL_Delay(2000);
Garbage collection
Before we exit, we must destroy all the objects we have created using the various SDL_DestroyX functions and complete the SDL.
SDL_DestroyTexture(tex); SDL_DestroyRenderer(ren); SDL_DestroyWindow(win); SDL_Quit();
End of the lesson
If successful, at startup you should see the image in the entire window, and after two seconds the program will end. In case of problems, make sure the SDL is installed and configured correctly. Detailed instructions for installing and configuring SDL for various platforms are available
here .
See you soon in
lesson 2: do not put everything in main .