1
\$\begingroup\$

I am programming a turn-based game, 2D tile-based, overhead view. I have an update function and a render function running in separate threads. When it's the player's turn, the player can e.g.

  • select a target tile from the map
  • then a popup menu with the available interactions appears
  • player selects interaction and the interaction gets executed

One tedious way is the following:

GameLoopUpdate():
        switch( interaction_state )
            case tile_selected:
                lookup_interactions_for_selected_tile()
                break
            case tile_and_interaction_selected()
                execute_interaction_at_tile()
                break
             default:
                break

Of course the above does not scale when the interactions get complex.

Conceptually, I would like it to be more like:

KeyListener():
    if tile is clicked
        set_tile_selected()

GameLoopUpdate():
    if tile is selected:
        interaction  = spawn_thread_interaction_selection()
        execute_interaction_at_tile( interaction )

where the spawned thread would somehow override the input listeners AND the rendering. But this looks bad as well.

Another idea (I'm starting to consider implementing this) is the following:

GameLoopUpdate():
    if it's player's turn
        set next state as PlayerState_Base
    else
        run ai turn

PlayerState_Base():
    if tile is selected
        set next state as PlayerState_TileSelected

PlayerState_TileSelected():
    if interaction is selected
        execute interaction
        set player's turn as done

where each state above would have dedicated key listener and rendering functions

Any other ideas?

\$\endgroup\$
2
\$\begingroup\$

You can't block the main game loop waiting for input. Instead, create some sort of state where you display the popup and listeners for the buttons. When the button is clicked then update your state.

\$\endgroup\$
  • \$\begingroup\$ Sorry, I forgot to specify that the update() function runs as a separate thread, while rendering is done in the main thread, and as such I can block it. \$\endgroup\$ – Babis Oct 28 '14 at 10:33
  • \$\begingroup\$ It's still a bad practice to block a thread while waiting for user input. It's much cleaner to take an asynchronous approach. \$\endgroup\$ – Mouscellaneous May 23 '16 at 8:40
1
\$\begingroup\$

I would recommend you use event handlers. This can be found fairly easily online, but I will give you a quick run-down to save some time for you.

Lets say you have an object that, if hovered over and left-clicked, will fire off an event to be handled in the game class.

I would recommend having each of these objects encapsulated in its own class, and having an event fire from within said object.

https://github.com/shroeder/GameRPG/tree/LukesBranch/Game/Game : Please reference the code found in the Menu Button Class in my github. Here you can see :

  1. How an event is declared
  2. How an event is raised
  3. How an event is handled in another class

You can see I have a class MenuButton, that can be instanciated on the fly and used over and over again. When I instanciate the Menu Button Class, It has events that can be raised on click, and handled in the PauseMenu Class. For additional examples you can reference my Checkbox Class and Slider Class.

Hopefully from my game's code you can see how you will raise your events and handle them. Event's are essentially just listeners that are waiting for a certain set of criteria (mouse hovering over a button, and clicked) to be met. When that criteria is met your objects fire events that tell the game class to handle them in a certain manner.

I hope this helps you, let me know if you have more issues during your project.

\$\endgroup\$
  • \$\begingroup\$ I know what event handlers are and I already use them for other parts of the game. Event handlers do not help me here as I want a full state transition when an event is fired (e.g. different rendering function different key/mouse handlers), while keeping the old state "on hold", and when the new state finishes, several frames later, I'd like to just resume from where I left. \$\endgroup\$ – Babis Oct 28 '14 at 14:25
  • \$\begingroup\$ What you want is different scenes then. \$\endgroup\$ – Shroeder Oct 28 '14 at 14:30
1
\$\begingroup\$

I think you should consider the various screens as many different programs. Or let's say, different screens. A screen can render and update by a given dt (delta-time).
The different screens should pile-up, and all should render in proper order, but only the top-most one should update (by dt).
Of course, you need some kind of messaging (through a hashmap/map?) in between screens to make this work.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.