Search code examples
c++sdl

SDL inputs only working sometimes


I am experimenting with keyboard input in SDL and I have encountered a strange problem. Whenever I get input it only outputs the appropriate response sometimes (Clicking X only sometimes closes the program, pressing 1 only sometimes outputs "you pressed 1". Here is my main code:

#include <iostream>
#include <SDL.h>

#include "Screen.h"
#include "Input.h"
using namespace std;

int main(int argc, char *argv[]) {
    Screen screen;
    Input input;
    if (screen.init() == false) {
        cout << "Failure initializing SDL" << endl;
    }

    while (true) {

        if (input.check_event() == "1") {
            cout << "You pressed 1" << endl;
        } else if (input.check_event() == "quit") {
            break;
        }

    }

    SDL_Quit();
    return 0;

and here is my Input class:

#include <iostream>
#include <SDL.h>
#include "Input.h"
using namespace std;
string Input::check_event() {
    while (SDL_PollEvent(&event)) {
        if (event.type == SDL_QUIT) {
            return "quit";
        }
        else if(event.type == SDL_KEYDOWN){
            switch(event.key.keysym.sym){
            case SDLK_1:
                return "1";
            }
        }
    }
    return "null";
}

Any help would be appreciated!


Solution

  • From the documentation of SDL_PollEvent():

    If event is not NULL, the next event is removed from the queue and stored in the SDL_Event structure pointed to by event.

    Analyzing your code:

        if (input.check_event() == "1") {
    

    This removes the event, whatever it is, from the queue.

        } else if (input.check_event() == "quit") {
    

    Say the return value of the 1st call to check_event() was "quit", then this call won't return "quit" again, because this information is now lost.

    To fix that, call check_event() only once per loop iteration and store the result in a temporary variable. Then use only that variable in the conditions:

    while (true) {
        string event = input.check_event();
        if (event == "1") {
            cout << "You pressed 1" << endl;
        } else if (event == "quit") {
            break;
        }
    }