I am having an issue with SDL2 where I want to see and use two different button textures at different times in different places using enum states. Each button is linked to a mousebuttonup event.
They do indeed appear and disappear on cue when the enum state changes. However, I can still click the respective invisible button when it's not being rendered. How do folks solve this problem?
This is only possible if rendering the UI is separate from processing the UI's logical state. The way to solve the problem is to couple the two processes.
There is no "general" process to do this, but quite frequently you can draw the button (or perhaps, queue the button's texture to be drawn) when processing the state of the game.
Ah, thank you. I've had it drilled into me to decouple everything whenever possible. I think I understand. So, right now my game loop is:
1. process input event handler, which links button presses to actions including gui state init
2. enum state switch
2x. render enum state x background and buttons
What else do I need to nest within the enum state switch to couple the UI rendering and processing? Do I need to run my event handler multiple times?
I've had it drilled into me to decouple everything whenever possible.
Sure, but the state is dependent so it doesn't make sense.
The game can be thought of as a filter whose input is the state of the user input devices (mouse, keyboard, controllers, etc.) and whose output is a sequence of audio and video frames.
The relevant part of your game loop should have access to the current state of user input and its own internal state. If the game state requires you to draw a menu, you can draw (or queue the drawing) of the menu exactly when you check its state.
For example in the main game loop you could have something along the lines of:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// - `ctx` is the I/O context, a handle to the resources needed to produce
// graphical and auditory output.
// - `user_input_state` is the state of the virtual pointer at least.
// - `text_label` draws the button.
// - `button` both draws the button and returns whether `user_input_state`
// indicates the button is clicked.
// Additional arguments to `text_label` and `button` that I didn't show might
// include position, size, style, and so on.
if (current_state == game_state::in_main_menu)
{
text_label(ctx, "My Title");
if (button(ctx, user_input_state, "Play"))
current_state = game_state::gameplay_loop;
if (button(ctx, user_input_state, "Quit"))
current_state = game_state::prompt_to_save_and_quit;
}
This is a book I bought before I knew the author provides it for free online: https://gameprogrammingpatterns.com/contents.html
Just wanted to drop a good resource, it discusses state machines as well as decoupling.
Thank you. So, I should nest the input, or functions that call up the input, or pointers to the input inside their respective game states like I do for the rendering. Time to tweak some more.
Oh, thanks! By the Group of Four? Yes, I've found game programming patterns very helpful. I didn't even know most of the concepts in there were even a thing before I ran across them in that ebook. Command patterns, state machines, and decoupling were definitely three eye openers.