lundi 6 décembre 2021

How does the command pattern solve the problem of hard-wired commands/requests?

I'm reading Game Programming Patterns by Robert Nystrom and have a question about the command pattern.

In the first example of the Configuring Input section, an if/else statement hard-codes game actions to console buttons:

void InputHandler::handleInput()
{
  if (isPressed(BUTTON_X)) jump();
  else if (isPressed(BUTTON_Y)) fireGun();
  else if (isPressed(BUTTON_A)) swapWeapon();
  else if (isPressed(BUTTON_B)) lurchIneffectively();
}

Since the key mappings are hard-coded at compile-time, the user cannot change/configure them according to their preferences at run-time. The command pattern is then introduced as a solution to this problem:

// ***Command interface***
class Command
{
public:
  virtual ~Command() {}
  virtual void execute() = 0;
};

// ***Concrete commands***
class JumpCommand : public Command
{
public:
  virtual void execute() { jump(); }
};

class FireCommand : public Command
{
public:
  virtual void execute() { fireGun(); }
};

[...]


// ***Input handler***
class InputHandler
{
public:
  void handleInput();

  // Methods to bind commands...

private:
  Command* buttonX_;
  Command* buttonY_;
  Command* buttonA_;
  Command* buttonB_;
};

void InputHandler::handleInput()
{
  if (isPressed(BUTTON_X)) buttonX_->execute();
  else if (isPressed(BUTTON_Y)) buttonY_->execute();
  else if (isPressed(BUTTON_A)) buttonA_->execute();
  else if (isPressed(BUTTON_B)) buttonB_->execute();
}

Questions

But it's not clear to me how the command pattern helps to make the input mappings run-time configurable. There must be some table in the GUI that allows the user to specify a key for each action type: <commandName, key>, but how do we create these key bindings at runtime?

I think we would need to use the new keyword to initialise the pointers, e.g. buttonX_ = new JumpCommand;, but I'm not sure exactly how to create the bindings and I don't understand why this cannot be done with an if/else at run-time.

I have some experience with JS and none with C++, so would be grateful if someone who is familiar with both languages could help me flesh out/understand what's going on in this example.

Aucun commentaire:

Enregistrer un commentaire