What happens to the remaining events if you break out of the PollEvent loop?

Imagine you are polling for events and suddenly you get the input Esc, and you want to switch state to the pause menu immediately without flushing the event Queue.

Can you describe to me what happens in such a situation and how it differs from doing things normally.

Maybe the question is confusing to you, but I don’t really get events. Is every input ever put in the event queue? If you move a mouse, do you get infinite events constantly? Or does only the mouse event get constantly overwritten and updated? Like, if you pressed a button now, released it, and then polled the events, would you get both or just the release action?

Where can I read more how this works?

All unpolled events will remain on the “event queue” until the next time you call SDL_PollEvent or other event-removing function. The events are stored in the order that they occur, so it actually should not be an issue in the scenario that you put forth.
(Keep in mind that if you switch scenes on key-down the user will still have their finger down when the scene changes which means the escape key-up will happen on your pause screen).

I still would recommend that you move the processing of most events outside of the event loop by setting “state flags”. Your “update section” can then deal with all state changes in a single frame that way, and you regain control of the order in which the events are dealt with for the entire frame.

There are high DPI mice that can fire events at about a thousand times per second, and even a regular mouse can produce multiple events per frame. In this instance you will get each event in the order in which they occur.

You would get both events.

Side Note:
There is a limit of 65535 event spaces on the queue. If you happen to overflow that limit then new events will be ignored/dropped until you begin to clear the queue by polling the events again.

2 Likes

Amazing reply. Thanks.

Should I use SDL_FlushEvent(s) functions to ease the event load if I want to do one action per frame?

If there are 1000 mouse events in the queue and I need 1 to give me the last mouse position, wouldn’t it be good to flush the rest? Or if I want a keyboard button, and there are 1000 mouse events because I moved a mouse, wouldn’t it be wasteful for the event loop to run 1000 times for nothing?

It’s fine to do one “action” per frame, but try to think of the mouse motion events as a sequence; the motion events are telling you a story of where the mouse has been, not just the start point and the end point for the frame. Even worse, somewhere buried in that story there was a click and a release, and where the click happened and where it was released change the meaning of the story.

What I mean is that there’s a lot of information that needs to be polled and then ignored, especially for a turn-based program. A single action will likely consist of many events. You can’t really just grab the first event and flush the rest because you would capture only a fragment of the whole story. You need to sift through and purposefully grab the important relevant information.

Here’s an example where I’m showing hover state and mouse-down states of a grid. Even though I am polling all possible events in the event loop, I am only processing the events that are important to the program.

#include <SDL2/SDL.h>

int main()
{
	SDL_Init(SDL_INIT_EVERYTHING);
	SDL_Window * win = SDL_CreateWindow("Title", 10, 10, 500, 500, SDL_WINDOW_SHOWN);
	SDL_Renderer * screen = SDL_CreateRenderer(win, -1, SDL_RENDERER_PRESENTVSYNC);

	SDL_Rect cell = {0, 0, 32, 32};
	SDL_Point mousePos;
	bool mouseDown = false;
	bool showTile = false;
	bool run = true;
	while(run)
	{
		SDL_Event ev;
		while(SDL_PollEvent(&ev))
		{
			switch(ev.type)
			{
				case SDL_MOUSEMOTION:
					// this will run multiple times per frame
					// but I only care where the end points are per frame.
					// So I'll just over-write the variable.
					// In this case, mousePos represents the end state of the mouse.
					mousePos = {ev.motion.x, ev.motion.y};
					break;
				case SDL_MOUSEBUTTONDOWN:
					mouseDown = true;
					break;
				case SDL_MOUSEBUTTONUP:
					mouseDown = false;
					break;
				case SDL_QUIT:
					run = false;
					break;
			}
		}
		// Update section, check state of the mouse and act on that data
		if(!SDL_PointInRect(&mousePos, &cell))
		{
			// the mouse has moved far enough to initiate an action.
			cell.x = mousePos.x - (mousePos.x % cell.w);
			cell.y = mousePos.y - (mousePos.y % cell.h);
		}
		showTile = false;
		if(mouseDown)
		{
			// show tile is my example of an "action" (sorry it's not an impressive action)
			showTile = true;
		}

		// drawing section
		SDL_SetRenderDrawColor(screen, 120, 10, 20, 255);
		SDL_RenderClear(screen);
		SDL_SetRenderDrawColor(screen, 200, 200, 200, 255);
		SDL_RenderDrawRect(screen, &cell);
		if(showTile)
		{
			SDL_RenderFillRect(screen, &cell);
		}
		SDL_RenderPresent(screen);
	}
	SDL_Quit();
}
1 Like