Using SDL2: Events
Tags: sdl2, c, events
Published: 2020-08-18 23:34:13

Games by definition need the quality of being interactive in order to be considered one. A video game typically is interacted through input devices like a joystick or gamepad on consoles and on PCs keyboards and mice are the preferred option. Keys are pressed, the mouse is moved and buttons are clicked.

All of these aforementioned actions produce what are called events. In SDL and like many other graphical libraries the way you find out what keys are pressed, the coordinates of the mouse and what, if any, mouse buttons are being clicked is by polling for events.

Internally, SDL has a queue or more specific an event queue. If you don't know what a queue is, you can more or less think about it as a line of people at the checkout. The first people to enter the line are the first people served. We call this a FIFO data structure or First In First Out.

As the user interacts more with the keyboard and mouse the more the queue is filled with events. Adding to the queue is called enqueuing and the opposite is called dequeuing where you take items off the queue or polling as it is referred to in SDL.

To poll events off the queue, use the `SDL_PollEvent` function.

The only argument it takes is a pointer to an `SDL_Event` structure which is basically an `enum` plus a `union`. For any type of event that SDL sends to the queue and can be polled by the programmer there is a corresponding event structure that is placed in the `union` of `SDL_Event`.

For example, if the event's type is equal to the `enum` constant `SDL_MOUSEMOTION` this means the mouse has moved within confines of the window and can be accessed through the structure `SDL_MouseMotionEvent` to get the relevant information that the programmer needs. The SDL documentation provides all possible events that can be generated here: https://wiki.libsdl.org/SDL_Event

Because it is possible to have multiple events on the queue at any given time, it is desirable to continuously poll the queue until we exhaust it. `SDL_PollEvent` returns one if we still have events on the queue and zero if empty.

```cpp
#include <iostream>
#include <SDL2/SDL.h>

/* Helper function to convert the number mapped to the buttons
   on the mouse to a readable string. This function does
   not handle all possible mouse buttons. */
char const *convert_button_number_to_string(int button)
{
    char const *result = "NO_BUTTON";
    switch (button)
    {
        case SDL_BUTTON_LEFT:
        result = "left";
        break;

        case SDL_BUTTON_MIDDLE:
        result = "middle";
        break;

        case SDL_BUTTON_RIGHT:
        result = "right";
        break;

        default:
        break;
    }

    return result;
}

int main()
{
    SDL_Init(SDL_INIT_EVERYTHING);
    SDL_Window *window = SDL_CreateWindow("SDL2 Window",
                                          SDL_WINDOWPOS_UNDEFINED,
                                          SDL_WINDOWPOS_UNDEFINED,
                                          1280,
                                          720,
                                          0);

    SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);
    SDL_Event event;
    bool running = true;
    while (running)
    {
        while (SDL_PollEvent(&event) > 0)
        {
            switch (event.type)
            {
                case SDL_QUIT:
                std::cout << "Quitting application\n";
                running = false;
                break;

                case SDL_MOUSEMOTION:
                std::cout << "Mouse Position = { "
                          << event.motion.x << " "
                          << event.motion.y << " }\n";
                break;

                case SDL_MOUSEBUTTONDOWN:
                case SDL_MOUSEBUTTONUP:
                std::cout << convert_button_number_to_string(event.button.button)
                          << " mouse button " << ((event.button.state == SDL_PRESSED) ? "pressed" : "released");
                std::cout << "\n";
                break;

                case SDL_KEYDOWN:
                case SDL_KEYUP:
                std::cout << "Key " << (char)event.key.keysym.sym << " "
                          << ((event.key.state == SDL_PRESSED) ? "pressed" : "released") << "\n";
                break;
            }
        }

        SDL_RenderPresent(renderer);
    }

    SDL_DestroyWindow(window);
    SDL_Quit();
}
```

Above is something to help you get started with SDL events. It only handles very basic events like closing of the application, key presses and mouse events like movement and use of the mouse buttons.

To find this and the rest of the code for the series up to this point and in the future go to the SDL2 Tutorial Code repository: https://github.com/Noah11012/sdl2-tutorial-code

And I'll see you all in my next article!