Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

c++ - SDL Mouse Click

So, I'm currently working on an options menu for my game, I have a button that when pressed it changes it's text to the next resolution in an array, so basically the user presses this button to change their resolution to the next string in the array.

My problem is getting the click event.

Right now, when the user presses the button, it returns true while the mouse is down, instead of when the mouse is pressed. I want to only return true in the mouse event when the mouse is pressed.

I've looked around, and everything I've found seems to be similar to what I've done or, as I said, returning true while the mouse is down, instead of the initial click.

My events are handled in a EventManager singleton, and here are the functions that I see as necessary:

My update function, this is where the event is polled, it is worth noting I'm using a private SDL_Event named "e".

void EventManager::update(){
    while(SDL_PollEvent(&e)){
        SDL_GetMouseState(&mouseX, &mouseY);
        switch(e.type){
            case SDL_QUIT:
                running = false;

        }
    }
}

My mousePress function, where I want a mouse press returned.

int EventManager::mousePress(){
    if(e.type == SDL_MOUSEBUTTONDOWN){
        return e.button.button;
    }
    return 0;
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Instead of using SDL_GetMouseState(), which gets you the actual state of the mouse (thats probably where its name comes from ;) ), use the event you are polling. SDL should give you a SDL_MouseButtonEvent which contains the informations you need and should only be queued once.

See https://wiki.libsdl.org/SDL_MouseButtonEvent

Edit to clarify what i mean:

You would use something like this:

void EventManager::update(){
    SDL_Event e;
    while(SDL_PollEvent(&e)){
        switch(e.type){
            case SDL_QUIT:
                running = false;
                break;
            case SDL_MOUSEBUTTONDOWN:
                //do whatever you want to do after a mouse button was pressed,
                // e.g.:
                mousePress(e.button);
                break;

        }
    }
}

Inside your mousePress-Function you can then test, which of the mouse buttons has been pressed:

void EventManager::mousePress(SDL_MouseButtonEvent& b){
  if(b.button == SDL_BUTTON_LEFT){
    //handle a left-click
  }
}

This works, because SDL_PollEvent will only return exactly once for every Event. If theres no new Event, it will return an empty Event. So 1 click = 1 times SDL_PollEvent() with e being of type SDL_MOUSEBUTTONDOWN afterwards and 1 times SDL_PollEvent() with e being of type SDL_MOUSEBUTTONUP afterwards. If you call SDL_PollEvent() in between or afterwards, it will return 0 and leave e as an Empty Event, not calling the switch at all. If you respond to MOUSEBUTTONDOWN or MOUSEBUTTONUP or both is up to you...

I've also declared the SDL_Event a local variable to update(). Why? The Idea behind an Event is, that theres an Event-Object whenever some event has occured. Then you react to the event and forget about it. So theres no need to have a global variable. If you want to prevent constant construction/destruction, you can also declare it to be static. But thats just some hint, not related to your original question.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...