Disable Event Polling Temporarily

Hi there,

I’m a beginner to both C++ and SDL2.0. To warm up, I’m making a slot machine game, and I’ve been stuck for a week on the problem of preventing multiple spins from being queued up. The spinReelsRandom() function is what starts a series of loops that generate random numbers in here.

The game operates perfectly right now except for the fact that a player who repeatedly hits the Space button during a spin (common practice for slot players) is queuing up spins that play out immediately after the user is done. I want to ignore input starting right after the first time the user presses the spacebar to start the spin until the spinReelsRandom() function is complete.

What I’ve already tried:

I’m able to get the desired result by using SDL_SetEventFilter (commented out below) in the main loop. My eventFilter is simply returning 1. However, for some reason, this prevents SDL_Quit from working. My guess as tp why this works is because the filter is only returning 1 while there are no events waiting to be polled since it’s outside the event polling loop, preventing users from queuing spins until the spinReelsRandom function is complete. If there’s an explanation, and a way to re-enable SDL_Quit, this could be it!

Moving the filter into the procedure right after pressing the spacebar doesn’t seem to work, and I’ve tried following up with a SDL_SetEventFilter(NULL, NULL) to reset the event filter after the spin is complete but it doesn’t seem to work.

I’ve also tried using an “isSpinning” flag that flips true while the reel is spinning and using a check on initiating a spin, but as soon as the flag flips back to false once the spin is complete, the additional polled spins begin.

Is there something I can be doing with SDL_PeepEvents? Any advice is greatly appreciated!

Here’s the main loop after initialization, with my event being “e”:

while (!quit)

    {
        while (SDL_PollEvent(&e) != 0)

        {           

// When an event is polled, this sets a filter to stop polling for more events until that action is completed.
// Note: This is what’s stopping the repeated spins, however it has disabled the quit functionality.
// SDL_SetEventFilter(eventFilter, &e);

            switch (e.type)
            {

            case SDL_QUIT:

                quit = true;

                break;

            case SDL_KEYDOWN:

                switch (e.key.keysym.sym)
                {

                case SDLK_SPACE:

                    //Function that continuously spins the reels until they reach a random destination
                    spinReelsRandom();

                    SDL_Delay(25);

                    break;

                case SDLK_0:

                    cout << "This works";

                    break;

                case SDLK_ESCAPE:

                    quit = true;

                    break;
                }

            }

            //Final Spin Cleanup
            spinCleanup();

}

}

So a better way to do this, if I’m understanding correctly, is to not hang out in spinReelsRandom(). Most game loops look like this:

while (the_game_is_still_going) {
    // SDL_PollEvents() in here, decide what to do with space bar, including reject if you should.
    check_for_input_events();

    // decide what the spinning numbers are at this moment, if spinning
    run_the_simulation_a_little_more();  

    // paint.
    redraw_the_screen();
}

This takes a little more work, but it means you never get stuck in a function when you might have more than one thing that needs to be progressing.

That being said, the not-best, but most-simple solution here is to ignore SDLK_SPACE if one happens in less than X milliseconds after a spin completes:

void spinReelsRandom(void) {
    static Uint32 earliest_time_for_next_spin = 0;
    if (!SDL_TICKS_PASSED(SDL_GetTicks(), earliest_time_for_next_spin)) {
        return;  // too soon, don't let them spin.
    }

    // Your spin code happens here.

   earliest_time_for_next_spin = SDL_GetTicks() + 250;  // make them wait 1/4 of a second to try again.
}    

Trying to disable SDL event polling is probably not the path you should take on this in any case.

–ryan.

1 Like

Another option would be to create a flag and temporary SDL_Event and have something like this:

if(!flag)
  SDL_PollEvent(&normal_event);
else
  SDL_PollEvent(&temp_event);

That will simply poll and discard events so that you won’t receive events until your flag has been changed. It won’t require much change in your code to test out.

Thanks for your advice!

I received similar (if less specific) advisement on StackOverflow and ended up with a solution that matches almost exactly what you described. It seems that loops within loops are generally a bad idea!

To break down the solution, I changed the While() loop within spinReelsRandom() that spins the reels into an If() statement that checked if the “isSpinning” flag is TRUE and incremented the reels towards their destinations one tick. Pressing the Spacebar now only flips the flag to TRUE if it is already FALSE. Once the reels are done spinning, “isSpinning” is changed to FALSE to allow another spin.

I’m using the same loop that checks for events to also render each frame, rather than starting a new loop within the event loop, in the same order you described, aside from rendering at the beginning of the loop so players who haven’t performed any actions yet still see the screen and the reels.

To elaborate, this solves my original problem because even though I’m still polling for a Spacebar event during the spin, the only action Space performs is switching the isSpinning flag to TRUE if it is already FALSE. Spamming the spacebar during the spin is registered but doesn’t change anything unless the reels have all reached their destinations. Polling during a Spin now also means I’ve solved the issue where players couldn’t quit mid-spin (since I didn’t return to the event polling loop until the spin loop was done).

I appreciate your additional explanation of the non-ideal solution as well. It would be tough to implement in my slot machine since the reels don’t spin for the exact same amount of time each spin since the destinations are random. It doesn’t vary much but this is useful information for when I implement other type of screens like showing a payout, etc.

1 Like

Or just extend the usual loop like this:

SDL_Event event;
while(SDL_PollEvent(&event))
{
	if(ignoreEvents)
	{
		continue;
	}

	// your usual event handling code below here
	// ...
}