1
\$\begingroup\$

I have a simple 2-D breakout clone. It works fine, except for one bug.

If I move mouse over game window, it will get input from mouse(mouse movement), and event queue will instantly be flooded with this input. For example, if player pressed left arrow, but moved his mouse over a window before, he will have to wait enough frames for mouse events to get processed. Is there a way to ignore mouse event? At least these movement ones. Everything is okay when mouse doesn't move, but after it moves it's terrible.

I'm using SDL 2.0, programming on Debian-based linux. Using C++.

Code for handling events looks like this(requested):

void gameEngine::HandleEvents()
{
    if( SDL_PollEvent(&gameEvent) != 0 )
    {
        HandleEngineEvents();
        gameLevel.HandleEvents(gameEvent);
    }
}

HandleEngineEvents() :

void gameEngine::HandleEngineEvents()
{
    if( gameEvent.type == SDL_QUIT)
    {
        running = false;
    }
    else if( gameEvent.type == SDL_KEYDOWN && gameEvent.key.repeat == 0 )
    {
        if( gameEvent.key.keysym.sym == SDLK_ESCAPE )
        {
            running = false;
        }
    }
}

Level::HandleEvents() :

void Level::HandleEvents(SDL_Event& gameEvent)
{
    player.HandleEvents(gameEvent);
}

Player::HandleEvents() :

void Player::HandleEvents(SDL_Event& gameEvent)
{
    if(gameEvent.type == SDL_KEYDOWN && gameEvent.key.repeat == 0)
    {
        switch(gameEvent.key.keysym.sym)
        {
        case SDLK_RIGHT:
             velocity += 1;
            break;
        case SDLK_LEFT:
            velocity -= 1;
            break;
        default:
            break;
        }
    }
    else if(gameEvent.type == SDL_KEYUP && gameEvent.key.repeat == 0)
    {
        switch(gameEvent.key.keysym.sym)
        {
        case SDLK_RIGHT:
             velocity -= 1;
            break;
        case SDLK_LEFT:
            velocity += 1;
            break;
        default:
            break;
        }
    }
}
\$\endgroup\$
  • \$\begingroup\$ Could you show the relevant part of your code where you handle events? \$\endgroup\$ – nathan Nov 21 '13 at 20:01
  • \$\begingroup\$ @nathan - Here you are. This code is executed every frame. I will also add, that flooding event queue doesn't affect anything but input processing - game is updated and rendered without problem. \$\endgroup\$ – MatthewRock Nov 21 '13 at 20:31
6
\$\begingroup\$

The documentation says about SDL_PollEvent:

Use this function to poll for currently pending events.

And you are supposed to use it this way (still from the doc):

while (1) {
    SDL_Event event;
    while (SDL_PollEvent(&event)) {
         // handle your event here
    }
    // do some other stuff here -- draw your app, etc.
}

In fact, you can have several events occurring between frames and the way you are doing it, you will only handle one event per frame because you call the function once. To proceed all the events in the queue, you have to loop on SDL_PollEvent returns 0 (no more event in the queue).

So just to explain a bit more, if you have 15 mouse dragging events from the frame N, with your code, you will handle one of them. Then, in the frame N+1, you could have a mouse click event, it will be added to the queue after the 14 remaining dragging events. So you would need to wait N+14 to see your click event handled.

So i would say, replace your if statement by a while statement.

EDIT: it doesn't really answer your question since i don't tell you how to filter events but it's not the cause of your problem.

\$\endgroup\$
  • \$\begingroup\$ That solved the answer. When I get enough reputation, I will give you guys +1. Thanks :) \$\endgroup\$ – MatthewRock Nov 21 '13 at 21:17
4
\$\begingroup\$

You can use the SDL function SDL_SetEventFilter as detailed here:

http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlseteventfilter.html

Basically, it takes as a parameter a function to use as a filter which events will be passed through and then determined as valid or invalid. The function should return 1 if valid or 0 if invalid.

For example, you may define a filter function:

int isMouseEvent(const SDL_Event* event)
{
    if (event->type == SDL_MOUSEMOTION)
        return 0;
    return 1;
}

Then somewhere else in the program set up the SDL_SetEventFilter:

// code bla bla    
SDL_SetEventFilter(isMouseEvent);

I hope this was clear. It solved the exact same problem for me.

EDIT: I just noticed that you are using a different version of SDL, so the answer may be slightly different in your case. According to http://www.ginkgobitter.org/sdl/?SDL_SetEventFilter you may need to specify an extra parameter in your filter function but it seems the basic logic is exactly the same.

\$\endgroup\$
  • \$\begingroup\$ Actually answer with while loop was better, but if I could, i would give you +1, for this answer may be helpful in the future. \$\endgroup\$ – MatthewRock Nov 21 '13 at 21:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.