0
\$\begingroup\$

The 2017 Thread "How to improve my input handling in GLFW?" is brilliant! Exactly my question and what seems like some great solutions.

However "Tyyppi_77" is hard for me to understand as a beginner. For starters:

1) how is addBinding called and when in the flow? Can you describe what the parameter Callback% callback is and its purpose?

I'll stop there for now. Ty!

class Window
{
public:
    using Callback = std::function<void()>;

    void addBinding(int key, const Callback& callback)
    {
        m_Callbacks[key].push_back(callback);
    }

    void onKeyPress(int key)
    {
        for (Callback& callback : m_Callbacks[key])
        {
            callback();
        }
    }
private:
    std::map<int, std::vector<Callback>> m_Callbacks;
};
\$\endgroup\$
  • 1
    \$\begingroup\$ Don't forget to include links to the posts in question, or even better, excerpts of the relevant material right in the body of your question itself. The easier you make it for folks to understand what you're talking about, the faster you'll tend to get answers. \$\endgroup\$ – DMGregory Mar 22 at 20:31
  • 1
    \$\begingroup\$ It would also help greatly if you could specify where you are stuck. \$\endgroup\$ – Tyyppi_77 Mar 22 at 20:40
0
\$\begingroup\$

Note: This answer expands on https://gamedev.stackexchange.com/a/150166/35344.

Let's take a player entity that has a few methods for movement:

struct Player {
    void moveLeft() {
        xVel = -1
    }

    void moveRight() {
        xVel = 1
    }
};

Then, with a setup such as the following, we can bind the movement methods to our callback manager (called Window here). The binding is performed in initialization, but you'd also perhaps want to perform this when new objects that need to listen to keyboard events are instantiated, or even when the player switches their keybindings (all though other approaches might be more suitable for that, however those are beyond the scope of this question).

int main() {
    Window window;
    setupGlfw(window);

    Player player;
    window.addBinding(KEY_LEFT, std::bind(&Player::moveLeft, &player));
    window.addBinding(KEY_RIGHT, std::bind(&Player::moveRight, &player));

    // Begin gameloop
}

The key here is std::bind, which takes a member function pointer, and an instance of the owning class, and creates an std::function<void()> for us, that we register as a callback to the specific key event.

The parameter Callback that addBinding accepts is a bound function call. Its purpose is to allow generic objects and functions to be bound to the same event handler (Window), as we could just as well pass around static member functions, functions in the global scope or even lambdas to the callback manager.

Note that our current implementation leaves a few details out, including memory management, which are left as an exercise to the reader (as they are way beyond the scope of this question).

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ m_CallBacks takes a vector of Callbacks? I would think that the key-value pair would only need a single link. I.e the key is the literal key and the value is the callback. Thanks \$\endgroup\$ – RabbitAGoGo Mar 25 at 17:54
  • \$\begingroup\$ We use a map of vectors to allow specifying a set of functions to call for each key. The system could easily be changed to use the same callback for every key (taking the key as a parameter), in which case we would only need a single vector. \$\endgroup\$ – Tyyppi_77 Mar 25 at 18:16

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.