Question on SDL_Poll and SDL_Wait
I've been having a problem with these functions in SDL. Basically it comes down to this, the user can click to start the game and then use esc to load the menu, there click to save, load, whatever. Both of these functions use SDL_PollEvent (I've also tried to use SDL_Wait too). The interesting thing is... if you click numerous times anywhere in the menu except where you need to click to activate something, then get out of the menu, it acts as if you clicked in the game and registers them all (basically in game, a click advances the text). I'm curious if this is because my computer registers a mouse click too fast? (I've noticed this in my game too, so I had to delay events to keep it from happening). Or, does initiating two SDL_PollEvents both queue the events in there own stacks and get to them when they can? I'm thinking of making it all run off one event system through the main loop but I don't want to make my main block to large and confusing (although it already is ;) ). Thanks in advance! EsperKnight Reverse engineering is the sincerest form of flattery. -- Engineers' saying in Silicon Valley (Rick Cook)
SDL provides you one event queue, which fills up with various events. You need to process or explicitly ignore all of them, as soon as you can. If you're only checking one event each time you call SDL_PollEvent, then you're gonna get a backlog.
Ahh makes sense. Thanks for the reply. I guess I'll have to figure out away to make it work with one then :) Out of curiosity, do you know if there is a way to clear the event queue? I've tried looking but haven't found a function, but I'm thinking if you can, it might clear all of windows event queue (I'm thinking they're running off the same thing, just SDL filters them). Thanks for the reply!
EsperKnight
Reverse engineering is the sincerest form of flattery. -- Engineers' saying in Silicon Valley (Rick Cook)
EsperKnight
Reverse engineering is the sincerest form of flattery. -- Engineers' saying in Silicon Valley (Rick Cook)
Quote:
Basically it comes down to this, the user can click to start the game and then use esc to load the menu, there click to save, load, whatever. Both of these functions use SDL_PollEvent (I've also tried to use SDL_Wait too). The interesting thing is... if you click numerous times anywhere in the menu except where you need to click to activate something, then get out of the menu, it acts as if you clicked in the game and registers them all (basically in game, a click advances the text).
To get around the problem you mentioned in the first post, you will need to use game states so this will not happen. I know exactly what you are talking about, for I once had the same problem. Here's a psuedo code/C++ example:
string state = "Title Screen";...void Update(){ Get Mouse State( x1 y1 ) if( state == "Title Screen") { if( OnGUIButton( x1,y1 ) ) { New Game(); state = "Level 1"; } } else if ( state == "Level 1" ) { FireRocket(); } ...}
This is more of a game logics problem I think. You just need to set a flag to tell how it processes each event at what time. You should only have one messaging loop that processes all of the events. The other problem is that you need to make sure you only processess a mouse click once per mouse release, ie don't process mouse down, but mouse up.
Now at first this will all look kind of messy, but there are a few things you can do to make it much neater and faster. I used a method of function pointers to set the update code that needs to be called whenever the game state is changed. This way, I am not always checking to see what needs to be called each drame. If you are intrested in that approach, I can hack up some code for it, I think I remember it all [wink].
Kylotan is super correct about the event queues. You will essentiall process all events, but you do not need to worry about filtering them out with the filter events SDL function. That is just too confusing and is a waste of time. You should use SDL_PollEvent though.
- Drew
this is a classic problem with taking input too fast. there are a few ways to get around this, but IMO the most elegant solution is the one suggested in the Enginuity series. Here is my Input class based on that tutorial:
and implementation:
basically, it takes input and records it for 2 frames, so that it can know if a key was JUST pressed (this only executes one time, even if you hold a key down forever), is being held down, just released, or has been released, same with mouse, etc. to use the class, just call Update() each frame somewhere. then you can call the functions Key_Down(), etc. to determine these things. read the enginuity article for more details.
class Input{ public: Input(); ~Input(); void Update(); void Update_Mouse(); void Process_Input_Message(const SDL_Event &event); //getting key functions bool Cur_Key(int index) { return keys[index] != 0; } bool Old_Key(int index) { return old_keys[index] != 0; } bool Key_Down(int index) { return ( Cur_Key(index))&&(!Old_Key(index)); } bool Key_Still_Down(int index) { return ( Cur_Key(index))&&( Old_Key(index)); } bool Key_Up(int index) { return (!Cur_Key(index))&&( Old_Key(index)); } bool Key_Still_Up(int index) { return (!Cur_Key(index))&&(!Old_Key(index)); } //now the mouse functions bool Cur_Mouse(int button) { return (buttons&SDL_BUTTON(button))!=0; } bool Old_Mouse(int button) { return (old_buttons&SDL_BUTTON(button))!=0; } bool Mouse_Down(int button) { int x,y; SDL_GetMouseState(&x,&y); if(y >= 0 && x >=0) return ( Cur_Mouse(button))&&(!Old_Mouse(button)); return false; } bool Mouse_Still_Down(int button) { int x,y; SDL_GetMouseState(&x,&y); if(y >= 0 && x >=0) return ( Cur_Mouse(button))&&( Old_Mouse(button)); return false; } bool Mouse_Up(int button){ return (!Cur_Mouse(button))&&( Old_Mouse(button)); } bool Mouse_Still_Up(int button){ return (!Cur_Mouse(button))&&(!Old_Mouse(button)); } void Get_Mouse_Pos(int &x,int &y){SDL_GetMouseState(&x,&y);} private: //keyboard int key_count; unsigned char *keys, *old_keys; //mouse unsigned int buttons; unsigned int old_buttons;};
and implementation:
Input::Input(){ unsigned char *temp_keys = SDL_GetKeyState(&key_count); keys = new unsigned char [key_count];//(unsigned char*)malloc(sizeof(unsigned char) * key_count); memcpy(keys,temp_keys,key_count); old_keys = new unsigned char [key_count];// (unsigned char*)malloc(sizeof(unsigned char) * key_count);}void Input::Process_Input_Message(const SDL_Event &event){ switch(event.type) { case SDL_ACTIVEEVENT: { /* Something's happend with our focus * If we lost focus or we are iconified, we * shouldn't draw the screen */ bool active = true; if (event.active.gain == 0)//, we set this to false active = false; systm->Set_Window_Focus(active); } break; case SDL_QUIT: { systm->done = true; } break; case SDL_KEYDOWN: { if(event.key.keysym.sym == SDLK_ESCAPE) systm->Done() = true; } break; }//end of switch event.type}void Input::Update(){ SDL_EnableUNICODE(1); while(SDL_PollEvent(&event)) { Process_Input_Message(event); for(std::list<Widget*>::iterator it = Widget::widget_list.begin(); it != Widget::widget_list.end(); ++it)//std::list<Widget*>::iterator it = Widget::widget_list.begin(); it != Widget::widget_list.end(); ++it) (*it)->Process_Input_Message(event); } SDL_EnableUNICODE(0); //for keyboard memcpy(old_keys,keys,key_count); unsigned char *temp_keys = SDL_GetKeyState(&key_count); memcpy(keys,temp_keys,key_count); //for mouse old_buttons = buttons; buttons = SDL_GetMouseState(NULL,NULL);}Input::~Input(){ delete [] keys; delete [] old_keys;}
basically, it takes input and records it for 2 frames, so that it can know if a key was JUST pressed (this only executes one time, even if you hold a key down forever), is being held down, just released, or has been released, same with mouse, etc. to use the class, just call Update() each frame somewhere. then you can call the functions Key_Down(), etc. to determine these things. read the enginuity article for more details.
FTA, my 2D futuristic action MMORPG
Thanks for all the replys! Graveyard filla, you just answered my next question :) My newest problem is with holding a key down with SDL_PollEvent. Was trying to get it so I could hold down a key to skip the text yet be able to push ESC and have it load the menu. Of course, having a fast processor, it kills you on just pressing a key with the SDL_PollEvent (or at least thats what I'm seeing), my menu loads up about 5 times (I can see it flicker, since pressing esc again turns it off). Of course, using SDL_WaitEvent, even with repeat enabled, it seems you have to cause another event just to get it to register a key being held down (I hold down ctrl to skip my text yet, unless I move the mouse, it doesn't register, strange I think). But I'm not sure if this is an error on my systems part or SDLs. Ah well. Also, thanks Drew_Benton, never thought about using events to do what I need to do... I was just using a if and else to switch into different functions and returning out of them... looks ugly but I might switch it with the though of just using states (depends how easy I can do it now ;) ). Makes more sense and looks easier on the eye :) Thanks everybody!
EsperKnight
Reverse engineering is the sincerest form of flattery. -- Engineers' saying in Silicon Valley (Rick Cook)
EsperKnight
Reverse engineering is the sincerest form of flattery. -- Engineers' saying in Silicon Valley (Rick Cook)
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement