📜 ⬆️ ⬇️

SDL2: Basics

Unfortunately, even on the official wiki, it is almost impossible to find any examples of using SDL2.x, what can we say about runet. Trying to figure it out, I found only a couple of articles that a third of my questions did not cover either.
SDL 2.x is significantly different from 1.x and even if in the past you had to work with it, now you risk not understanding anything.

Today we will write a simple program that displays the background and zoomed sprite of a character moving with WASD and arrows. + We will understand how to work with the mouse in SDL.

To work we need :

All this can be easily found on the Internet.

Let's start from the beginning:
')

SDL Initialization


Let's begin, perhaps, with creation of object of class SDL_DisplayMode .
It is very useful to us if we want to have an application for the whole screen.
This object must be created before initializing the SDL itself.

SDL_DisplayMode displayMode; 


After that, you need to initialize the SDL itself:
 if (SDL_Init(SDL_INIT_EVERYTHING) != 0){ std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl; return 1; } 


The SDL_INIT_EVERYTHING flag initializes all SDL subsystems. If you just need something specific, you can find a complete list on the wiki.

Now we need to get the monitor settings we work with.
To do this, we create an variable in which 0 will be returned if everything went well and equate it with the functions SDL_GetDesktopDisplayMode(*int displayIndex, SDL_DisplayMode* mode) .
If the first argument is written 0, then the function will refer to the main monitor. We will be able to read all the received parameters from the displayMode object.
  int request = SDL_GetDesktopDisplayMode(0,&displayMode); 


It's time to do our window !
It's all very simple, create a pointer to an object of the SDL_Window class and call the function
 SDL_Window* SDL_CreateWindow(const char* title, int x, int y, int w, int h, Uint32 flags) 


Everything here is of course clear, but just in case I will explain what's what.

SDL_WINDOW_SHOWN - makes the window visible.

As a result, the output is the following code:
 SDL_Window *win = SDL_CreateWindow("Hello World!", 0, 0, displayMode.w, displayMode.h, SDL_WINDOW_SHOWN); if (win == nullptr){ std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl; return 1; } 


Now we need to create a renderer :
 SDL_Renderer* SDL_CreateRenderer(SDL_Window* window, int index, Uint32 flags) 


Putting it all together and get:
 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; } 

Now SDL is ready to cooperate with us!

Output on display


It's time to take pictures.
First we need to create 2 objects of the SDL_Rect class.
This object will contain the physical parameters of our textures, such as width, height, and position in the window.
 SDL_Rect player_RECT; player_RECT.x = 0; //    player_RECT.y = 0; //   Y player_RECT.w = 333; //  player_RECT.h = 227; //  SDL_Rect background_RECT; background_RECT.x = 0; background_RECT.y = 0; background_RECT.w = displayMode.w; background_RECT.h = displayMode.h; 

And a couple of lines, so that later we could zoom our character:
 const int player_WIGHT = 333; //   const int player_HEIGH = 227; //   double TESTtexture_SCALE = 1.0; //   


And so we got to download textures.
I will show 2 ways:

But first, a small digression!
I think those who used to work with SDL1.x didn’t need explanations, but I’ll tell you how the SDL works, all of a sudden (maybe you never know) someone is not familiar with it.
In SDL there are 4 main classes / structures involved in displaying images on the screen: SDL_Texture , SDL_Surface , SDL_Rect , SDL_Render .

We have already talked about the last 2, let's now briefly discuss the remaining ones.

After that, this object is sent to the render:
 SDL_RenderCopy(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Rect* srcrect, const SDL_Rect* dstrect) SDL_RenderPresent(SDL_Renderer* renderer) 


Well, with the theory figured out, it's time to practice!

Option number ONCE:
This method is tied to the libraries SDL_mixer.h and SDL_Image.h , so do not shout at me be surprised when errors will flow to you by connecting only SDL2.

Its peculiarity is that it transmits an alpha channel without bicycles.
 SDL_Texture *player = IMG_LoadTexture(ren,"..\\res\\player.png"); 

Now we have the character texture ready to appear on the screen. But before that, we still need to create a background.

Option number TWO:
We will create the background using pure SDL. Just because we can!
Code here!
 SDL_Surface *BMP_background = SDL_LoadBMP("..\\res\\background.bmp"); if (BMP_background == nullptr){ std::cout << "SDL_LoadBMP Error: " << SDL_GetError() << std::endl; return 1; } SDL_Texture *background = SDL_CreateTextureFromSurface(ren, BMP_background); SDL_FreeSurface(BMP_background); //   if (player == nullptr){ std::cout << "SDL_CreateTextureFromSurface Error: " << SDL_GetError() << std::endl; return 1; } 

When working with pure SDL, you should never forget to check for errors!

And finally, Hurray, it's time to bring it to the screen!
 SDL_RenderClear(ren); //  SDL_RenderCopy(ren,background,NULL,&background_RECT); //    SDL_RenderCopy(ren, player, NULL, &player_RECT); //    SDL_RenderPresent(ren); //!! 


Developments


I think it is not necessary to explain that from 2 pictures of the game will not work.
Time to add some dynamics to our miracle!

First you need to create a couple of infinite loops that work while there are events and there is no way out:
 SDL_Event event; bool quit = false; while(!quit) while(SDL_PollEvent(&event)) { SDL_PumpEvents(); //  . } 


It's time to do events directly.
In SDL, there are 2 ways to read events from controllers:


It remains to display the result on the screen. To do this, add to the loop:
 render_UPDATE(ren, ARRAY_textures, ARRAY_rect, ARRAY_texturesState); //     SDL_RenderPresent(ren); 

Close the loop!
And in the end we need only complete our program.

A curtain!


Before we finish everything, we need to remove our textures from memory.
 SDL_DestroyTexture(player); SDL_DestroyTexture(background); 


And now you can safely shut down the SDL and programs:
 SDL_DestroyRenderer(ren); SDL_DestroyWindow(win); SDL_Quit(); return 1; 

Final, ovation! We wrote the first program on SDL2! With what I congratulate us!

PS


It took me 2 days to create such an elementary program. There are so few manuals on SDL2 on the Internet that it is easier to shoot yourself than to find something.
I really hope that this article was useful to you and this monster will not take as much time from you as I do.

Source can be downloaded here.

Source: https://habr.com/ru/post/201392/


All Articles