Hello! This is the third lesson on SDL 2. Information is taken from
this source. I didn't like the lessons on handling Lasy Foo 'events, so I'll write my own, but the material can be found
here and
here .
And we begin, welcome to the lesson
Developments
Today we will teach our program to respond to events with the help of
John .
')
So, let's begin. we connect SDL 2 and we create 3 global variables and 2 constants.
#include <SDL2/SDL.h> const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; SDL_Window *win = NULL; SDL_Surface *scr = NULL; SDL_Surface *john = NULL;
Further we write 3, already known and past lessons, functions:
Init int init() { if (SDL_Init(SDL_INIT_VIDEO) != 0) { std::cout << "Can't init: " << SDL_GetError() << std::endl; system("pause"); return 1; } win = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); if (win == NULL) { std::cout << "Can't create window: " << SDL_GetError() << std::endl; system("pause"); return 1; } scr = SDL_GetWindowSurface(win); return 0; }
Load int load() { john = SDL_LoadBMP("john.bmp"); if (john == NULL) { std::cout << "Can't load image: " << SDL_GetError() << std::endl; system("pause"); return 1; } return 0; }
Quit int quit() { SDL_FreeSurface(john); SDL_DestroyWindow(win); SDL_Quit(); return 0; }
Attention (!), If you copy the code from the previous lesson, do not forget: change to
john .
All that should be said: I decided to show errors at the stage of initialization and image loading.
So let's continue. open
main and call the functions
Init and
Load .
int main (int argc, char ** args) { if (init() == 1) { return 1; } if (load() == 1) { return 1; } }
Now we will analyze how any application works. Any program you run (Google Chrome, Paint, Minecraft) has a main loop that runs a great number of times. It is necessary for dynamism. Previously, we wrote a program that simply showed a smiley for 2 seconds, but in order for the program to learn how to respond to user actions (or at least infinitely show an image), it needs a
While loop.
It will be constantly repeated and in it we will be able to do whatever we want, for example, to handle events. But before starting the main loop, create several variables.
bool run = true; SDL_Event e; SDL_Rect r; int x = 0; int y = 0; rx = x; ry = y;
Now we will sort everything out. First, create a
run variable of type
boolean . This variable is responsible for the execution of the cycle: while the program is running, it is equal to
true , but if we want to stop the execution, then we assign this variable to
false . Next, create an
e object of the
SDL_Event class. In the properties of this object will be the data of the received event, then will be more. After that we create the
r object of the
SDL_Rect class. This is the rectangle required to draw an object with any coordinates we need. Then we create variables
x and
y of type
int . Immediately assign their values ​​to zero. These will be the coordinates of our character. The next item we assign to the variables
rx and
ry are the values ​​of
x and
y, respectively.
rx and
ry are the coordinates of the rectangle
r .
It's time to open the main loop.
while (run) { while(SDL_PollEvent(&e) != 0) { if (e.type == SDL_QUIT) { run = false; } if (e.type == SDL_KEYDOWN) { if (e.key.keysym.sym == SDLK_UP) { y -= 1; } if (e.key.keysym.sym == SDLK_DOWN) { y += 1; } if (e.key.keysym.sym == SDLK_RIGHT) { x += 1; } if (e.key.keysym.sym == SDLK_LEFT) { x -= 1; } } } rx = x; ry = y; SDL_FillRect(scr, NULL, SDL_MapRGB(scr -> format, 255, 255, 255)); SDL_BlitSurface(john, NULL, scr, &r); SDL_UpdateWindowSurface(win); }
Let's break this code down. We have two cycles. The first one is the main one, which works on the
run variable, as mentioned earlier. The second loop is responsible for handling events.
The
SDL_PollEvent () function opens a queue of events received in one execution of the main loop, deletes the last event and writes data about this event into the variables of the object that we passed to this function, we have this
e . This function returns 0,
NULL, or
false if all events from the queue have been deleted, so we write the
while condition
(SDL_PollEvent (& e)! = NULL) .
Look further: the first check we have is to click the cross in the window frame. If we press it, then the
type variable of the object
e is assigned the value
SDL_QUIT . If this happens, we assign the
run variable to
false and the loop ends.
Next, I wrote a keystroke test. If the button is pressed, the
e.type variable is
SDL_KEYDOWN . Next, check the key values. The variable
e.key.keysym.sym stores the value of the button. We compare this value with the necessary one and perform certain actions. We will change the coordinate of John. If the up arrow is pressed, then
y is decreased by 1, if down, then it increases, etc. I think you understand the point.
After processing the events, we reassign
rx and
ry to update the coordinates of Man. Then we write the already familiar function
SDL_FilRect , it has a very large role. If we didn’t write it, then when moving, John would leave an ugly mark, and so, each frame we draw a background in white and draw a sprite on top of it. After that we draw our hero with the function
SDL_BlitSurface . Here we will use our rectangle
r , or rather its variables
x and
y , to draw not just the top left, but with some necessary coordinates. Next, just update the window.
After the main loop, write
return quit (); to complete the program.
That's it, this lesson is over. Here is the code:
Code #include <SDL2/SDL.h> #include <iostream> const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; SDL_Window *win = NULL; SDL_Surface *scr = NULL; SDL_Surface *john = NULL; int init() { if (SDL_Init(SDL_INIT_VIDEO) != 0) { std::cout << "Can't init: " << SDL_GetError() << std::endl; system("pause"); return 1; } win = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); if (win == NULL) { std::cout << "Can't create window: " << SDL_GetError() << std::endl; system("pause"); return 1; } scr = SDL_GetWindowSurface(win); return 0; } int load() { john = SDL_LoadBMP("john.bmp"); if (john == NULL) { std::cout << "Can't load image: " << SDL_GetError() << std::endl; system("pause"); return 1; } return 0; } int quit() { SDL_FreeSurface(john); SDL_DestroyWindow(win); SDL_Quit(); return 0; } int main (int argc, char ** args) { if (init() == 1) { return 1; } if (load() == 1) { return 1; } bool run = true; SDL_Event e; SDL_Rect r; int x = 0; int y = 0; rx = x; ry = y; while (run) { while(SDL_PollEvent(&e) != NULL) { if (e.type == SDL_QUIT) { run = false; } if (e.type == SDL_KEYDOWN) { if (e.key.keysym.sym == SDLK_UP) { y -= 1; } if (e.key.keysym.sym == SDLK_DOWN) { y += 1; } if (e.key.keysym.sym == SDLK_RIGHT) { x += 1; } if (e.key.keysym.sym == SDLK_LEFT) { x -= 1; } } } rx = x; ry = y; SDL_FillRect(scr, NULL, SDL_MapRGB(scr -> format, 255, 255, 255)); SDL_BlitSurface(john, NULL, scr, &r); SDL_UpdateWindowSurface(win); } return quit(); }
And I say goodbye to you, all the while!
<< Previous lesson