SDL 2 Lessons: Lesson 3 - Events

    Hello! This is the third lesson in SDL 2. Information is taken from this source. I didn't like the Lasy Foo 'event handling tutorials, so I'll write my own, but the material can be found here and here .

    And we begin, welcome to the lesson

    Events


    Today we will teach our program to respond to events with the help of John .

    So, let's begin. connect SDL 2 and create 3 global variables and 2 constants.

    #include 
    const int SCREEN_WIDTH = 640;
    const int SCREEN_HEIGHT = 480;
    SDL_Window *win = NULL;
    SDL_Surface *scr = NULL;
    SDL_Surface *john = NULL;
    

    Next, we write 3 functions already known from the last lesson:

    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 to change the smile to john .

    All that should be said: I decided to show errors at the initialization and image loading stage.

    So, let's continue. open main and call the Init and Load functions .

    int main (int argc, char ** args) {
        if (init() == 1) {
            return 1;
        }
        if (load() == 1) {
            return 1;
        }
    }
    

    Now let's see how any application works. Any program that you run (Google Chrome, Paint, Minecraft) has a main loop that runs a huge number of times. This is necessary for dynamism. Previously, we wrote a program that just showed a smile for 2 seconds, but in order for the program to learn how to respond to user actions (or at least display the image endlessly), it needs a While loop .

    It will be constantly repeated and in it we can already do what we want, for example, process events. But before you start the glan cycle, let's create some variables.

        bool run = true;
        SDL_Event e;
        SDL_Rect r;
        int x = 0;
        int y = 0;
        r.x = x;
        r.y = y;
    

    We’ll analyze everything now. First, create a run variable of type boolean . This variable is responsible for the execution of the loop: while the program is running, it is true , if we want to stop execution, then set this variable to false . Next, create an e object of class SDL_Event . The properties of this object will contain the data of the received event, further will be more detailed. After that we create an object r of the SDL_Rect class . This is the rectangle required to draw the object with some 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 the variables rx and ry the values x and y, respectively. rx and ry are the coordinates of the rectangle r .

    It's time to open the main cycle.

        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;
                    }
                }
            }
            r.x = x;
            r.y = y;
            SDL_FillRect(scr, NULL, SDL_MapRGB(scr -> format, 255, 255, 255));
            SDL_BlitSurface(john, NULL, scr, &r);
            SDL_UpdateWindowSurface(win);
        }
    

    Let's parse this code. We have two cycles. The first main - main, which operates a variable expense of the run , as mentioned earlier. The second loop is responsible for handling events.

    The SDL_PollEvent () function opens the queue of events received in one execution of the main loop, deletes the last event and writes data about this event to 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) .

    We look further: the first check we have is to click the cross in the window frame. If we click it, then the type variable of object e is assigned the value SDL_QUIT . If this happens, then we assign false to the run variable and the loop ends. Next, I wrote a keyboard keystroke test. If the button is pressed, then the e.type variable is equal to 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 desired and perform certain actions. We will change the coordinate of John. If the up arrow is pressed, then y

    decreases by 1, if down, then increases, etc. The bottom line, I think, you understand.

    After processing the events, reassign rx and ry to update the coordinates of the Man. Next, we write the already familiar function SDL_FilRect , it has a very large role. If we hadn’t written it, then John would have left an ugly mark on movement, and so, every frame we draw a white background and draw a sprite on top of it. After that, we draw our hero with the SDL_BlitSurface function . Here we will use our rectangle r , or rather its variables x and y , to draw not just at 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 all, this lesson is over. Here is such a code:

    The code
    #include 
    #include 
    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;
        r.x = x;
        r.y = 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;
                    }
                }
            }
            r.x = x;
            r.y = 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, bye everyone!

    << Previous lesson || Next lesson >>

    Also popular now: