Search code examples
csdlsdl-2

Event handling using SDL and C for my hobby game engine


I am building a hobby/minimalist/general 2d game engine using SDL and C as my programming language. Also following along with Lazy Foo Production tutorials. I use the C language for learning purposes.

I would like to implement a general event handler function, that would be able to run a user written function to handle a given event. Currently I am still in the beginning stages.

handler header file:

#ifndef HANDLER_H
#define HANDLER_H

#include <SDL2/SDL.h>
#include <stdarg.h>

int handle(SDL_Event e, void (*handler)(int args,...));

#endif

Client code:

        int quit = FALSE;
        SDL_Event e;
        while (quit == FALSE) {
                while (SDL_PollEvent(&e) != 0) {
                        if (e.type == SDL_QUIT) {
                                quit = TRUE;
                        }
                        //call to handle goes here
                }

                render_image(&dp,&i_p);
                update_display(&dp);
        }

Would it be suffecient to us a function pointer as the parameter to handle() or is there a better method to implementing a generic event handler.

My core goal for the engine in terms of event handling is to just be able to have the handler handle events that are polled in the game loop by using a function written by the end-user instead of hard coding in functions to handle every type of possible event.


Solution

  • If you want end-users to write the functions for handling the events, I would suggest relying on callbacks. The idea is that the end-user will dictate what event handler to call for each event type, whereas the game engine will dictate when to call the corresponding event handler.

    The user is provided with a struct of callbacks so that user code can define custom event handlers and configure these callbacks to refer to these custom functions. Then, the loop for event processing of the game engine calls those functions via the callbacks set up by the user.


    Example

    You could define different function types for different events:

    typedef void (*quit_handler_t)(void);
    typedef void (*keydown_handler_t)(SDL_Keycode);
    typedef void (*keyup_handler_t)(SDL_Keycode);
    

    That is, the handler for quitting takes no arguments, whereas those for a key going up and down takes an argument that represents the corresponding key.

    Then, you provide the client with a struct, event_handlers, that contains pointers to the event handlers and the end-user is supposed to populate:

    struct {
       quit_handler_t    quit;
       keydown_handler_t keydown;
       keyup_handler_t   keyup;
    } event_handlers;
    

    Finally, the game engine's loop for processing the events call those functions through the callbacks that were set up by the user:

    SDL_Event e;
    while (!quit && SDL_PollEvent(&e)) {
       switch(e.type) {
       case SDL_QUIT:
          event_handlers.quit();
          break;
       case SDL_KEYDOWN:
          event_handlers.keydown(e.key.keysym.sym);
          break;
       case SDL_KEYUP:
          event_handlers.keyup(e.key.keysum.sym);
          break;
       }
    }
    

    Note that the game engine could also initialize the event_handler struct with default event handlers. The end-user would be able to override that default behavior by modifying the members of event_handler.