Thread: Made an EventHandler - need feedback

  1. #1
    Registered User
    Join Date
    Dec 2016
    Posts
    20

    Made an EventHandler - need feedback

    So I've written a eventHandler that has a thread looping thorugh all relevant keys to check if they have been released (i.e last updated more than 100 ms ago). However as it currently stands, all relevant keys get checked, not only those who are being pressed. Is it worth the trouble of creating a linked list of keys currently being pressed just for this purpose? It's the last function: checkForRelease that could be optimzed through this.

    Also need (1) advice on how it currently works, if I should change something, and (2) how to save the events so that the relevant ones can be read inside a client function to be sent to the server at a synchronized time, im thinking it's wiser to separate the eventTrigger from how it's handled.

    [C] EventHandler - Pastebin.com
    Last edited by Tiago Redaelli; 12-27-2016 at 05:03 PM.

  2. #2
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    I would need to see the whole program.

  3. #3
    Registered User
    Join Date
    Dec 2016
    Posts
    20
    Quote Originally Posted by algorism View Post
    I would need to see the whole program.
    Currently the game loop is inside client.c, there are 3 threads atm, 1) renderer 2) eventHandler 3) Client: Game-loop. Other than that, there is not much to look at inside Client at the moment, other than the starting of threads.

    I was thinking there would be a function for: isKeyBeingPressed(SDl_Key key) {for keys like w, a, s, d, up, down, right, left and left mouse button0} and similarly isThereAPendingEvent(CustomEvent e) {for enter pressed, esc pressed and left mouse button pressed/released}. The client serves the event acording to game state for enter or esc and then removes it from pending. Haven't made the functionality for this yet in the eventHandler.

    Later the client will send the relevant key information to the server and listen to changes that are made coming from the server.
    Last edited by Tiago Redaelli; 12-27-2016 at 07:30 PM.

  4. #4
    Registered User
    Join Date
    Dec 2016
    Posts
    20
    I've made some updates. It contains linked lists now, and you can add/remove keys you want to search for. Working on to do something similar for mouse events.

    There is an issue with this part of the code:

    Code:
                    
    if (event.type == SDL_MOUSEBUTTONDOWN)
    {
        if (event.button.button = SDL_BUTTON_LEFT)
        {
              printf("Left Mouse Pressed\n");
              buttonState[SDL_BUTTON_LEFT] = PRESSED;
        {
    }
    I seem to be able to register both left and right clicks as left clicks.

    Also I need to have a good way to check if a key/button was pressed during the previous game-loop cycle, but im not sure exactly how to do it.


    Here is some of the code I have so far:
    Code:
    /** File: client.c
    **/
    #include <SDL2/SDL.h>
    #include <stdio.h>
    #include <stdbool.h>
    #include "event_handler.h"
    #include "renderer.h"
    
    int main()
    {
        initSDL();
        renderer();
    
        addKeyToEventHandler(SDL_SCANCODE_W);
        addKeyToEventHandler(SDL_SCANCODE_A);
        addKeyToEventHandler(SDL_SCANCODE_S);
        addKeyToEventHandler(SDL_SCANCODE_D);
        addKeyToEventHandler(SDL_SCANCODE_ESCAPE);
        addKeyToEventHandler(SDL_SCANCODE_RETURN);
        addKeyToEventHandler(SDL_SCANCODE_RETURN2);
        addKeyToEventHandler(SDL_SCANCODE_UP);
        addKeyToEventHandler(SDL_SCANCODE_LEFT);
        addKeyToEventHandler(SDL_SCANCODE_DOWN);
        addKeyToEventHandler(SDL_SCANCODE_RIGHT);
    
        SDL_Thread *t_event_handler = SDL_CreateThread(eventHandler, "eventHandler", (void *)NULL);
    
        //removeKeyFromEventHandler(SDL_SCANCODE_ESCAPE);
    
    
        int count = 0;
        while (1)
        {
            int x, y;
            SDL_GetMouseState(&x, &y);
    
            if (isKeyBeingPressed(SDL_SCANCODE_W))
            {
                unsigned int i = SDL_GetTicks();
                i /= 1000;
                printf("%d: W is being pressed!\n", i);
                if (i >= 3 && i < 4)
                    count++;
                if (i == 5)
                    break;
            }
    
            if (isButtonBeingPressed(SDL_BUTTON_LEFT))
                printf("LEFT BUTTON IS BEING PRESSED\n");
    
    
            SDL_Delay(16);
        }
        printf("Count = %d", count);
    }
    
    int initSDL()
    {
        if (SDL_Init(SDL_INIT_VIDEO) != 0)
        {
            printf( "VIDEO could not initialize! SDL_Error: %s\n", SDL_GetError());
            exit(1);
        }
    }
    Code:
    /** File: event_handler.c
    **/
        #include <stdio.h>
        #include <stdbool.h>
        #include <SDL2/SDL.h>
        #include "event_handler.h"
        #include "event_handler_list.h"
    
        #define RELEASE_DELAY   50
        #define MAX_FOUND_KEYS  40
        #define PRESSED         true
        #define RELEASED        false
        #define MAX_KEYS        322
        #define MAX_Buttons     5
    
        int mouse_x;
        int mouse_y;
    
        bool buttonState[MAX_Buttons];
        bool keyState[MAX_KEYS];
        unsigned int keyTimeStamp[MAX_KEYS];
        SDL_Thread *eventHandlerThread = NULL;
    
        int getMouseX()
        {
            return mouse_x;
        }
    
        int getMouseY()
        {
            return mouse_y;
        }
    
        void addKeyToEventHandler(int key)
        {
            akAdd(key);
            printf("Key added: %d\n", key);
        }
    
        void removeKeyFromEventHandler(int key)
        {
            akRemove(key);
            printf("Key added: %d\n", key);
        }
    
        bool isKeyBeingPressed(int key)
        {
            return keyState[key] == PRESSED;
        }
    
        bool isButtonBeingPressed(int button)
        {
            return buttonState[button] == PRESSED;
        }
    
        void eventHandler()
        {
            const Uint8 *keys = SDL_GetKeyboardState(NULL);
    
    
            unsigned int timeStamp;
            for (int i = 0; i < MAX_KEYS; i++)
            {
                keyState[i] = RELEASED;
                keyTimeStamp[i] = 0;
            }
    
    
            while (true)
            {
                timeStamp = SDL_GetTicks();
                SDL_PumpEvents();
                SDL_Event event;
    
                while(SDL_PollEvent(&event))
                {
                    if (event.type == SDL_QUIT)
                    {
                        SDL_Quit(); // need to replaced with a client signa.
                        return;
                    }
                    if (event.type == SDL_MOUSEBUTTONDOWN)
                    {
                        if (event.button.button = SDL_BUTTON_LEFT)
                        {
                            printf("Left Mouse Pressed\n");
                            buttonState[SDL_BUTTON_LEFT] = PRESSED;
                        }
                    }
                    if (event.type == SDL_MOUSEBUTTONUP)
                    {
                        if (event.button.button = SDL_BUTTON_LEFT)
                        {
                            printf("Left Mouse Released\n");
                            buttonState[SDL_BUTTON_LEFT] = RELEASED;
                        }
                    }
                }
    
                SDL_GetMouseState(&mouse_x, &mouse_y);  // Get current mouse position
                checkForPressedKeys(keys);              // Check for pressed Keys
                checkForReleasedKeys();                 // Check for released Keys
                SDL_Delay(10);                          // Slows down the cycle
            }
        }
    
        void checkForPressedKeys(Uint8 *keys)
        {
            if (!akIsEmpty())
            {
                struct node_ak *ptr = akGetHead();
                unsigned int timeStamp = SDL_GetTicks();
                int i = 0, foundKeycode[40];
                while(ptr != NULL)
                {
                    if (keys[ptr->keycode] == PRESSED)
                    {
                        keyTimeStamp[ptr->keycode] =  timeStamp;
                        if (keyState[ptr->keycode] == RELEASED) {
                            keyState[ptr->keycode] = PRESSED;
                            printf("%d was pressed\n", ptr->keycode);
                            pkAdd(ptr->keycode);
                        }
                    }
                    ptr = ptr->next;
                }
            }
        }
    
        void checkForReleasedKeys()
        {
            if (!pkIsEmpty())
            {
                struct node_pk *ptr = pkGetHead();
                unsigned int timeStamp = SDL_GetTicks() - RELEASE_DELAY;
                int i = 0, foundKeycode[MAX_FOUND_KEYS];
    
                while(ptr != NULL)
                {
                    if (timeStamp > keyTimeStamp[ptr->keycode])
                    {
                        foundKeycode[i] = ptr->keycode;
                        i++;
                    }
                    ptr = ptr->next;
                }
                for (int j = 0; j < i; j++)
                {
                    printf("%d was released\n", foundKeycode[j]);
                    keyState[foundKeycode[j]] = RELEASED;
                    pkRemove(foundKeycode[j]);
                }
            }
        }
    Code:
    /** File: event_handler_list.c
    **/
    
    #include <stdio.h>
    #include <stdbool.h>
    #include <SDL2/SDL.h>
    #include "event_handler_list.h"
    
    //====================================================
    // Double-linked list: Available Keys (PK)
    //====================================================
    
        struct node_ak *head_ak = NULL; //this link always point to first Link
        struct node_ak *tail_ak = NULL; //this link always point to last Link
    
        struct node_ak* akGetHead()
        {
            return head_ak;
        }
    
        struct node_ak* akGetTail()
        {
            return tail_ak;
        }
    
        bool akIsEmpty()
        {
           return head_ak == NULL;
        }
    
        int akGetNumber()
        {
           int length = 0;
           struct node_ak *current_ak;
    
           for(current_ak = head_ak; current_ak != NULL; current_ak = current_ak->next){
              length++;
           }
           return length;
        }
    
        void akAdd(int key)
        {
            //create a link
            struct node_ak *link = (struct node_ak*) malloc(sizeof(struct node_ak));
            link->keycode = key;
    
            if(akIsEmpty()) {
              //make it the last link
              tail_ak = link;
            } else {
              //update first prev link
              head_ak->prev = link;
            }
    
            //point it to old first link
            link->next = head_ak;
    
            //point first to new first link
            head_ak = link;
        }
    
        struct node_ak* akRemove(int key)
        {
           //start from the first link
           struct node_ak* current_ak = head_ak;
           struct node_ak* previous = NULL;
    
           //if list is empty
           if(head_ak == NULL) {
              return NULL;
           }
    
           //navigate through list
           while(current_ak->keycode != key) {
    
              //if it is last node
              if(current_ak->next == NULL) {
                 return NULL;
              } else {
                 //store reference to current link
                 previous = current_ak;
    
                 //move to next link
                 current_ak = current_ak->next;
              }
           }
    
           //found a match, update the link
           if(current_ak == head_ak) {
              //change first to point to next link
              head_ak = head_ak->next;
           } else {
              //bypass the current link
              current_ak->prev->next = current_ak->next;
           }
    
           if(current_ak == tail_ak) {
              //change last to point to prev link
              tail_ak = current_ak->prev;
           } else {
              current_ak->next->prev = current_ak->prev;
           }
    
           return current_ak;
        }
    //====================================================
    // Double-linked list: Pressed Keys (PK)
    //====================================================
    
        struct node_pk *head_pk = NULL; //this link always point to first Link
        struct node_pk *tail_pk = NULL; // //this link always point to last Link
    
        struct node_pk* pkGetHead()
        {
            return head_pk;
        }
    
        struct node_pk* pkGetTail()
        {
            return tail_pk;
        }
    
    
        bool pkIsEmpty()
        {
           return head_pk == NULL;
        }
    
        int pkGetNumber()
        {
           int length = 0;
           struct node_pk *current_pk;
    
           for(current_pk = head_pk; current_pk != NULL; current_pk = current_pk->next){
              length++;
           }
           return length;
        }
    
        void pkAdd(int key)
        {
            //create a link
            struct node_pk *link = (struct node_pk*) malloc(sizeof(struct node_pk));
            link->keycode = key;
    
    
            if(pkIsEmpty()) {
              //make it the last link
              tail_pk = link;
            } else {
              //update first prev link
              head_pk->prev = link;
            }
    
            //point it to old first link
            link->next = head_pk;
    
            //point first to new first link
            head_pk = link;
        }
    
        struct node_pk* pkRemove(int key)
        {
           //start from the first link
           struct node_pk* current_pk = head_pk;
           struct node_pk* previous = NULL;
    
           //if list is empty
           if(head_pk == NULL) {
              return NULL;
           }
    
           //navigate through list
           while(current_pk->keycode != key) {
    
              //if it is last node
              if(current_pk->next == NULL) {
                 return NULL;
              } else {
                 //store reference to current link
                 previous = current_pk;
    
                 //move to next link
                 current_pk = current_pk->next;
              }
           }
    
           //found a match, update the link
           if(current_pk == head_pk) {
              //change first to point to next link
              head_pk = head_pk->next;
           } else {
              //bypass the current link
              current_pk->prev->next = current_pk->next;
           }
    
           if(current_pk == tail_pk) {
              //change last to point to prev link
              tail_pk = current_pk->prev;
           } else {
              current_pk->next->prev = current_pk->prev;
           }
    
           return current_pk;
        }
    Last edited by Tiago Redaelli; 12-28-2016 at 10:29 AM.

  5. #5
    Registered User
    Join Date
    Dec 2010
    Location
    Trinidad, CO (log cabin in middle of nowhere)
    Posts
    148
    event.button.button = SDL_BUTTON_LEFT
    Maybe missing = sign???

  6. #6
    Registered User
    Join Date
    Dec 2016
    Posts
    20
    Ye that was the issue. But after futher testing a bug happend in which it never found that a key had been released and thus continued to spam that it was being pressed.

    The built in keyboard repeat function is really causing me a hard time. I just want to detect the human keyboard events, not the automatically generated ones...
    Is there any reliable way to disable it in the program?

    I tried using SDL_EnableKeyRepeat(0, 0); Which supposedly should disable it, but alas it did no such thing.

    Other thing's i tried was to use SDL_FlushEvent(SDL_KEYDOWN) and SDL_FlushEvent(SDL_KEYUP); to see if that was causing any problem. But it just made matters worse.
    Last edited by Tiago Redaelli; 12-30-2016 at 07:12 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Just looking for Feedback
    By rTeapot in forum C++ Programming
    Replies: 8
    Last Post: 07-07-2012, 08:26 AM
  2. Looking For Feedback
    By Matty_Alan in forum C++ Programming
    Replies: 2
    Last Post: 05-27-2010, 04:33 PM
  3. K&R2, 1-24. Feedback
    By Tool in forum C Programming
    Replies: 0
    Last Post: 11-14-2009, 10:49 AM
  4. Feedback?
    By CornedBee in forum A Brief History of Cprogramming.com
    Replies: 8
    Last Post: 01-02-2004, 11:01 PM
  5. feedback, please...
    By major_small in forum C++ Programming
    Replies: 5
    Last Post: 08-24-2003, 08:17 PM

Tags for this Thread